···11extern crate std;
2233-use std::{boxed::Box, string::String, vec::Vec};
33+use std::{string::String, vec::Vec};
4455use serde::{Deserialize, Deserializer, de};
66···3737 Length(usize),
3838}
39394040-/// A boxed closure type, representing the operation to be executed by our Kat.
4141-type KatClosure<'s> = Box<dyn for<'a> Fn(&mut StrobeState, DataOrLength<'a>, bool) + 's>;
4040+// Given the name of the operation and its required parameters, run the STROBE operation.
4141+fn run_kat_operation(
4242+ op_name: &str,
4343+ meta: bool,
4444+ s: &mut StrobeState,
4545+ dol: DataOrLength,
4646+ more: bool,
4747+) {
4848+ let data = match dol {
4949+ DataOrLength::Length(len) => {
5050+ if !meta {
5151+ assert_eq!(op_name, "RATCHET", "Got length input without RATCHET op");
5252+ s.ratchet(len);
5353+ return;
5454+ } else {
5555+ assert_eq!(op_name, "RATCHET", "Got length input without RATCHET op");
5656+ s.meta_ratchet(len);
5757+ return;
5858+ }
5959+ }
6060+ DataOrLength::Data(data) => data,
6161+ };
42624343-// Given the name of the operation and meta flag, returns a closure that performs this operation.
4444-// Returns a boxed closure, because the input and output types of the closure have to fit all
4545-// possible STROBE operations and it is easier to erase that via boxing.
4646-fn get_operation<'s>(op_name: &'s str, meta: bool) -> KatClosure<'s> {
4747- let f = move |s: &mut StrobeState, dol: DataOrLength, more: bool| {
4848- let data = match dol {
4949- DataOrLength::Length(len) => {
5050- if !meta {
5151- assert_eq!(op_name, "RATCHET", "Got length input without RATCHET op");
5252- s.ratchet(len);
5353- return;
5454- } else {
5555- assert_eq!(op_name, "RATCHET", "Got length input without RATCHET op");
5656- s.meta_ratchet(len);
5757- return;
5858- }
5959- }
6060- DataOrLength::Data(data) => data,
6161- };
6363+ // To prevent streaming, reset ops *before* executing the operation
6464+ // in order to ensure the output state matches the KAT assertion
6565+ if !more {
6666+ s.reset_ops();
6767+ }
62686363- // To prevent streaming, reset ops *before* executing the operation
6464- // in order to ensure the output state matches the KAT assertion
6565- if !more {
6666- s.reset_ops();
6969+ // Note: we don't expect recv_MAC to work on random inputs. We test recv_MAC's
7070+ // correctness in basic_kats.rs. Also MAC sizes are 14 bytes in the KAT.
7171+ if !meta {
7272+ match op_name {
7373+ "AD" => s.ad(data),
7474+ "KEY" => s.key(data),
7575+ "PRF" => s.prf(data),
7676+ "send_CLR" => s.send_clr(data),
7777+ "recv_CLR" => s.recv_clr(data),
7878+ "send_ENC" => s.send_enc(data),
7979+ "recv_ENC" => s.recv_enc(data),
8080+ "send_MAC" => s.send_mac(data),
8181+ "recv_MAC" => s
8282+ .recv_mac::<14>(data.as_ref().try_into().unwrap())
8383+ .unwrap_or(()),
8484+ "RATCHET" => panic!("Got RATCHET op without length input"),
8585+ _ => panic!("Unexpected op name: {}", op_name),
6786 }
6868-6969- // Note: we don't expect recv_MAC to work on random inputs. We test recv_MAC's
7070- // correctness in basic_kats.rs. Also MAC sizes are 14 bytes in the KAT.
7171- if !meta {
7272- match op_name {
7373- "AD" => s.ad(data),
7474- "KEY" => s.key(data),
7575- "PRF" => s.prf(data),
7676- "send_CLR" => s.send_clr(data),
7777- "recv_CLR" => s.recv_clr(data),
7878- "send_ENC" => s.send_enc(data),
7979- "recv_ENC" => s.recv_enc(data),
8080- "send_MAC" => s.send_mac(data),
8181- "recv_MAC" => s
8282- .recv_mac::<14>(data.as_ref().try_into().unwrap())
8383- .unwrap_or(()),
8484- "RATCHET" => panic!("Got RATCHET op without length input"),
8585- _ => panic!("Unexpected op name: {}", op_name),
8686- }
8787- } else {
8888- match op_name {
8989- "AD" => s.meta_ad(data),
9090- "KEY" => s.meta_key(data),
9191- "PRF" => s.meta_prf(data),
9292- "send_CLR" => s.meta_send_clr(data),
9393- "recv_CLR" => s.meta_recv_clr(data),
9494- "send_ENC" => s.meta_send_enc(data),
9595- "recv_ENC" => s.meta_recv_enc(data),
9696- "send_MAC" => s.meta_send_mac(data),
9797- "recv_MAC" => s
9898- .meta_recv_mac::<14>(data.as_ref().try_into().unwrap())
9999- .unwrap_or(()),
100100- "RATCHET" => panic!("Got RATCHET op without length input"),
101101- _ => panic!("Unexpected op name: {}", op_name),
102102- }
8787+ } else {
8888+ match op_name {
8989+ "AD" => s.meta_ad(data),
9090+ "KEY" => s.meta_key(data),
9191+ "PRF" => s.meta_prf(data),
9292+ "send_CLR" => s.meta_send_clr(data),
9393+ "recv_CLR" => s.meta_recv_clr(data),
9494+ "send_ENC" => s.meta_send_enc(data),
9595+ "recv_ENC" => s.meta_recv_enc(data),
9696+ "send_MAC" => s.meta_send_mac(data),
9797+ "recv_MAC" => s
9898+ .meta_recv_mac::<14>(data.as_ref().try_into().unwrap())
9999+ .unwrap_or(()),
100100+ "RATCHET" => panic!("Got RATCHET op without length input"),
101101+ _ => panic!("Unexpected op name: {}", op_name),
103102 }
104104- };
105105-106106- Box::new(f)
103103+ }
107104}
108105109106// Runs the test vector and compares to the expected output at each step of the way
···126123 stream,
127124 expected_output,
128125 expected_state_after,
129129- }| {
130130- if name != "init" {
126126+ }| match name.as_str() {
127127+ "init" => {
128128+ // Check that the initial state matches what is expected in the KAT operation
129129+ assert_eq!(&strobe.state.0[..], expected_state_after.as_slice());
130130+ }
131131+ name => {
131132 // RATCHET inputs are given as strings of zeros instead of lengths. So just take the
132133 // length of the string of zeros.
133133- let input = if &name == "RATCHET" {
134134+ let input = if name == "RATCHET" {
134135 DataOrLength::Length(input_data.len())
135136 } else {
136137 DataOrLength::Data(input_data.as_mut_slice())
137138 };
138139139139- get_operation(&name, meta)(&mut strobe, input, stream);
140140+ run_kat_operation(name, meta, &mut strobe, input, stream);
140141141142 assert_eq!(&strobe.state.0[..], expected_state_after.as_slice());
142143