(&self, context: Context, argument_types: Vec<Type>)
| 63 | #[typetag::serde] |
| 64 | impl CustomOperationBody for LowMC { |
| 65 | fn instantiate(&self, context: Context, argument_types: Vec<Type>) -> Result<Graph> { |
| 66 | // Size of a single LowMC block (typically) |
| 67 | let block_size = match self.block_size { |
| 68 | LowMCBlockSize::SIZE128 => 128, |
| 69 | LowMCBlockSize::SIZE80 => 80, |
| 70 | }; |
| 71 | // Length of an encryption key |
| 72 | let key_size = LOW_MC_KEY_SIZE; |
| 73 | |
| 74 | // Check that the number of triples affected by a single substitution round doesn't exceed the number of bits in the block |
| 75 | if self.s_boxes_per_round > block_size / 3 { |
| 76 | return Err(runtime_error!( |
| 77 | "The number of S-boxes must be between 10 and 42" |
| 78 | )); |
| 79 | } |
| 80 | // Check that the number of encryption rounds doesn't exceed 20. |
| 81 | // The pre-generated random matrices support at most 20 rounds. |
| 82 | if self.rounds > 20 { |
| 83 | return Err(runtime_error!("The number of rounds can't exceed 20")); |
| 84 | } |
| 85 | |
| 86 | if argument_types.len() != 2 { |
| 87 | return Err(runtime_error!( |
| 88 | "LowMC should have 2 inputs: input and an encryption key" |
| 89 | )); |
| 90 | } |
| 91 | |
| 92 | if argument_types[0].get_scalar_type() != BIT { |
| 93 | return Err(runtime_error!("Input of LowMC must be binary")); |
| 94 | } |
| 95 | |
| 96 | let input_shape = argument_types[0].get_shape(); |
| 97 | let input_element_len = input_shape[input_shape.len() - 1]; |
| 98 | if input_element_len > block_size { |
| 99 | return Err(runtime_error!( |
| 100 | "Input bitstrings should be of length {}", |
| 101 | block_size |
| 102 | )); |
| 103 | } |
| 104 | |
| 105 | if argument_types[1] != array_type(vec![key_size], BIT) { |
| 106 | return Err(runtime_error!( |
| 107 | "LowMC key must be a binary array of length {}", |
| 108 | key_size |
| 109 | )); |
| 110 | } |
| 111 | |
| 112 | let g = context.create_graph()?; |
| 113 | |
| 114 | let input = g.input(argument_types[0].clone())?; |
| 115 | let key = g.input(argument_types[1].clone())?; |
| 116 | |
| 117 | // Pad input with zeros |
| 118 | let padded_input = if input_element_len < block_size { |
| 119 | let length_to_pad = block_size - input_element_len; |
| 120 | extend_with_zeros(&g, input, length_to_pad, false)? |
| 121 | } else { |
| 122 | input |
nothing calls this directly
no test coverage detected