1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Module providing an implementation of a cryptographic command processor.
18 
19 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::types::{
20     MemoryBufferReference::MemoryBufferReference, OperationData::OperationData,
21 };
22 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{
23     CryptoOperation::CryptoOperation,
24     MemoryBufferParameter::{
25         MemoryBuffer::MemoryBuffer as MemoryBufferAidl, MemoryBufferParameter,
26     },
27     OperationParameters::OperationParameters,
28     PatternParameters::PatternParameters,
29 };
30 use core::ffi::c_void;
31 use hwcryptohal_common::{err::HwCryptoError, hwcrypto_err};
32 use std::{os::fd::AsRawFd, ptr::NonNull};
33 use vm_memory::{volatile_memory::VolatileSlice, Bytes, VolatileMemory};
34 
35 use crate::crypto_operation::{CopyOperation, CryptographicOperation, ICryptographicOperation};
36 
37 const OUTPUT_MEMORY_BUFFER_FLAGS: u32 =
38     trusty_sys::MMAP_FLAG_PROT_READ | trusty_sys::MMAP_FLAG_PROT_WRITE;
39 const INPUT_MEMORY_BUFFER_FLAGS: u32 = trusty_sys::MMAP_FLAG_PROT_READ;
40 
41 /// `CmdProcessorState` is a state machine with 3 states:
42 ///
43 /// * `InitialState`: State machine operation starts here. No cryptographic operations can be
44 ///                   performed on this state (but copy operations are permitted). It is used to
45 ///                   set up memory buffers and Cryptographic operation parameters. We can go back
46 ///                   to this state from `RunningOperation` state after a `Finish` call.
47 /// * `RunningOperation`: Once a call to `SetOperationParameters` is performed, we move to this
48 ///                       state. Any call to `DataInput` on this state will immediately perform the
49 //                        requested cryptographic operation.
50 /// * `Destroyed`: Any call to `DestroyContext` will make the state machine move to this state. Once
51 ///                in this state, the state machine cannot be used anymore.
52 ///
53 /// The following diagram shows how we move between states. It is written in the form
54 /// [Current State] -> [Next State]: [Operation performed on current state]:
55 ///
56 /// `InitialState` -> `InitialState`: `CopyData`
57 ///         Call requires that an output buffer has been set and will immediately try to copy the
58 ///         data provided
59 /// `InitialState` -> `InitialState`: `DataOutput`
60 ///         Sets output buffer. Any previously set up DataOutput is not used after this.
61 /// `InitialState` -> `InitialState`: `SetMemoryBuffer`
62 ///         Sets an fd to be used by memory references. It can only be set once
63 ///         because currently output buffers will directly use the active memory buffer, instead of
64 ///         remembering which memory buffer was active at the moment the output was added. This
65 ///         should cover the current use cases, but could be refactored if needed.
66 /// `InitialState` -> `RunningOperation`: `SetOperationParameters`
67 ///         Starts executing cryptographic operation.
68 /// `RunningOperation` -> `RunningOperation`: `DataOutput`
69 ///         Sets output buffer. Any previously set up DataOutput is not used after this.
70 /// `RunningOperation` -> `RunningOperation`: `CopyData`
71 ///         Call requires that an output buffer has been set and will immediately try to copy the
72 ///         data provided. It can be used to implement some cryptographic protocols which decrypt
73 ///         only some areas and directly copy other areas
74 /// `RunningOperation` -> `RunningOperation`: `AadInput`
75 ///         Processes the provided data as Authenticated Additional Data
76 /// `RunningOperation` -> `RunningOperation`: `DataInput`
77 ///         Immediately processes the provided data. For operations like encryption or decryption on
78 ///         which we need to immediately generate data, this call requires that an output buffer has
79 ///         been already set up
80 /// `RunningOperation` -> `RunningOperation`: `SetPattern`
81 ///         Sets up a pattern of encrypted/unencrypted data to process on the subsequent calls to
82 ///         `DataInput`. Currently it is only used for AES CBC decryption (cbcs mode from IEC
83 ///         23001-7:2016)
84 /// `RunningOperation` -> `InitialState`: `Finish`
85 ///         Finish an ongoing cryptographic operation. Notice that this call can generate data as in
86 ///         the case of signing operations or padded encryption. This call will invalidate any
87 ///         settings done by `SetOperationParameters` or `SetPattern`
88 /// `RunningOperation` -> `RunningOperation`: `SetOperationParameters`
89 ///         Resets all cryptographic parameters set up on the previous `SetOperationParameters`
90 ///         operation and implicitly calls finish. Main use case is to reset IV for cbcs mode
91 ///         decryption without needing to call finish.
92 /// `RunningOperation` -> `Destroyed`: `DestroyContext`
93 ///         This context cannot be used anymore
94 /// `InitialState` -> `Destroyed`: `DestroyContext`
95 ///         This context cannot be used anymore
96 #[derive(Debug, PartialEq)]
97 enum CmdProcessorState {
98     InitialState,
99     RunningOperation,
100     Destroyed,
101 }
102 
103 pub(crate) enum DataToProcessBuffer<'a> {
104     VolatileSlice(VolatileSlice<'a>),
105     Slice(&'a mut [u8]),
106 }
107 
108 // `DataToProcess`is used to abstract away if the cryptographic operations are working on memory
109 // buffers or vectors.
110 pub(crate) struct DataToProcess<'a> {
111     start_index: usize,
112     buffer: DataToProcessBuffer<'a>,
113 }
114 
115 impl<'a> DataToProcess<'a> {
new_from_volatile_slice(buffer: VolatileSlice<'a>) -> Self116     pub(crate) fn new_from_volatile_slice(buffer: VolatileSlice<'a>) -> Self {
117         Self { buffer: DataToProcessBuffer::VolatileSlice(buffer), start_index: 0 }
118     }
119 
new_from_slice(buffer: &'a mut [u8]) -> Self120     pub(crate) fn new_from_slice(buffer: &'a mut [u8]) -> Self {
121         Self { buffer: DataToProcessBuffer::Slice(buffer), start_index: 0 }
122     }
123 
len(&self) -> usize124     pub(crate) fn len(&self) -> usize {
125         match &self.buffer {
126             DataToProcessBuffer::VolatileSlice(vs) => vs.len() - self.start_index,
127             DataToProcessBuffer::Slice(s) => s.len() - self.start_index,
128         }
129     }
130 
is_non_volatile_slice_backed(&self) -> bool131     pub(crate) fn is_non_volatile_slice_backed(&self) -> bool {
132         match &self.buffer {
133             DataToProcessBuffer::VolatileSlice(_) => true,
134             DataToProcessBuffer::Slice(_) => false,
135         }
136     }
137 
138     /// If self is backed by a non-volatile buffer, returns a slice of the specified
139     /// length, incrementing the current position. Return an error if self is volatile (use
140     /// `read_into_slice()` instead to make a copy of the data) or if the requested length exceeds
141     /// the slice capacity.
try_slice(&mut self, len: usize) -> Result<&[u8], HwCryptoError>142     pub(crate) fn try_slice(&mut self, len: usize) -> Result<&[u8], HwCryptoError> {
143         if len > self.len() {
144             return Err(hwcrypto_err!(
145                 BAD_PARAMETER,
146                 "end {} out of slice bounds for slice size {}",
147                 len,
148                 self.len()
149             ));
150         }
151 
152         if let DataToProcess { buffer: DataToProcessBuffer::Slice(slice), start_index } = self {
153             let slice_start = *start_index;
154             *start_index += len;
155             Ok(&slice[slice_start..slice_start + len])
156         } else {
157             Err(hwcrypto_err!(BAD_PARAMETER, "DataToProcess is backed by a VolatileSlice",))
158         }
159     }
160 
read_into_slice( &mut self, to: &mut [u8], len: Option<usize>, ) -> Result<(), HwCryptoError>161     pub(crate) fn read_into_slice(
162         &mut self,
163         to: &mut [u8],
164         len: Option<usize>,
165     ) -> Result<(), HwCryptoError> {
166         let len = len.unwrap_or(to.len());
167 
168         if len > to.len() {
169             return Err(hwcrypto_err!(
170                 BAD_PARAMETER,
171                 "end {} out of slice bounds for slice size {}",
172                 len,
173                 to.len()
174             ));
175         }
176 
177         if len > self.len() {
178             return Err(hwcrypto_err!(
179                 BAD_PARAMETER,
180                 "end {} out of slice bounds for slice size {}",
181                 len,
182                 self.len()
183             ));
184         }
185 
186         match &self.buffer {
187             DataToProcessBuffer::Slice(from) => {
188                 to[..len].copy_from_slice(&from[self.start_index..self.start_index + len])
189             }
190             DataToProcessBuffer::VolatileSlice(from) => {
191                 from.read_slice(&mut to[..len], self.start_index)?
192             }
193         };
194         self.start_index += len;
195         Ok(())
196     }
197 
append_slice(&mut self, from: &[u8]) -> Result<(), HwCryptoError>198     pub(crate) fn append_slice(&mut self, from: &[u8]) -> Result<(), HwCryptoError> {
199         if self.len() < from.len() {
200             return Err(hwcrypto_err!(
201                 BAD_PARAMETER,
202                 "slice size: {} is less than the slice provided {}",
203                 self.len(),
204                 from.len()
205             ));
206         }
207         match &mut self.buffer {
208             DataToProcessBuffer::VolatileSlice(to) => to.write_slice(from, self.start_index)?,
209             DataToProcessBuffer::Slice(to) => {
210                 to[self.start_index..(self.start_index + from.len())].copy_from_slice(from)
211             }
212         }
213         self.start_index += from.len();
214         Ok(())
215     }
216 
read_from_slice( &mut self, slice: &mut DataToProcess<'a>, len: Option<usize>, ) -> Result<(), HwCryptoError>217     pub(crate) fn read_from_slice(
218         &mut self,
219         slice: &mut DataToProcess<'a>,
220         len: Option<usize>,
221     ) -> Result<(), HwCryptoError> {
222         let read_len = len.unwrap_or(slice.len());
223 
224         if read_len > slice.len() {
225             return Err(hwcrypto_err!(
226                 BAD_PARAMETER,
227                 "len {} was greater than slice len {}",
228                 read_len,
229                 slice.len()
230             ));
231         }
232 
233         if self.len() < read_len {
234             return Err(hwcrypto_err!(
235                 BAD_PARAMETER,
236                 "slice size: {} is less than the slice provided size {}",
237                 self.len(),
238                 read_len
239             ));
240         }
241 
242         let from_start_index = slice.start_index;
243         let to_start_index = self.start_index;
244 
245         match (&slice.buffer, &mut self.buffer) {
246             (DataToProcessBuffer::Slice(from), DataToProcessBuffer::VolatileSlice(to)) => to
247                 .write_slice(
248                     &from[from_start_index..from_start_index + read_len],
249                     to_start_index,
250                 )?,
251             (DataToProcessBuffer::VolatileSlice(from), DataToProcessBuffer::VolatileSlice(to)) => {
252                 from.get_slice(from_start_index, read_len)?
253                     .copy_to_volatile_slice(to.get_slice(to_start_index, read_len)?)
254             }
255             (DataToProcessBuffer::Slice(from), DataToProcessBuffer::Slice(to)) => to
256                 [to_start_index..to_start_index + read_len]
257                 .copy_from_slice(&from[from_start_index..from_start_index + read_len]),
258             (DataToProcessBuffer::VolatileSlice(from), DataToProcessBuffer::Slice(to)) => from
259                 .read_slice(&mut to[to_start_index..to_start_index + read_len], from_start_index)?,
260         }
261         self.start_index += read_len;
262         slice.start_index += read_len;
263         Ok(())
264     }
265 
266     /// Grows the vector to the required size and return a `DataToProcess` to the newly allocated
267     /// portion
allocate_buffer_end_vector( vector: &'a mut Vec<u8>, buffer_size: usize, ) -> Result<DataToProcess<'a>, HwCryptoError>268     pub(crate) fn allocate_buffer_end_vector(
269         vector: &'a mut Vec<u8>,
270         buffer_size: usize,
271     ) -> Result<DataToProcess<'a>, HwCryptoError> {
272         let original_len = vector.len();
273         vector.try_reserve(buffer_size)?;
274         // Addition should be safe because try_reserve didn't fail
275         let new_len = original_len + buffer_size;
276         vector.resize_with(new_len, Default::default);
277         Ok(DataToProcess {
278             buffer: DataToProcessBuffer::Slice(&mut vector[original_len..new_len]),
279             start_index: 0,
280         })
281     }
282 }
283 
284 // Structure that keeps track of current output buffer
285 enum OutputData<'a> {
286     DataBuffer(&'a mut Vec<u8>),
287     MemoryReference(MemoryBufferReference, usize),
288 }
289 
get_mmap_prot_flags(memory_buffer: &MemoryBufferAidl) -> u32290 fn get_mmap_prot_flags(memory_buffer: &MemoryBufferAidl) -> u32 {
291     match memory_buffer {
292         MemoryBufferAidl::Input(_) => INPUT_MEMORY_BUFFER_FLAGS,
293         MemoryBufferAidl::Output(_) => OUTPUT_MEMORY_BUFFER_FLAGS,
294     }
295 }
296 
297 // `MemoryBufferReference` types do not contain the necessary information to
298 // know if it should operate on an Input or Output buffer. That information is provided by the
299 // Operation which contains the `MemoryBufferReference`. This wrapper preserves that information to
300 // be used along function call sequences.
301 #[derive(Copy, Clone)]
302 enum MemoryBufferReferenceWithType {
303     Input(MemoryBufferReference),
304     Output(MemoryBufferReference),
305 }
306 
307 impl MemoryBufferReferenceWithType {
len(&self) -> Result<usize, HwCryptoError>308     fn len(&self) -> Result<usize, HwCryptoError> {
309         match self {
310             MemoryBufferReferenceWithType::Input(buff_ref) => buff_ref.sizeBytes,
311             MemoryBufferReferenceWithType::Output(buff_ref) => buff_ref.sizeBytes,
312         }
313         .try_into()
314         .map_err(|e| {
315             hwcrypto_err!(BAD_PARAMETER, "buffer reference sizes cannot be negative: {:?}", e)
316         })
317     }
318 
start_offset(&self) -> Result<usize, HwCryptoError>319     fn start_offset(&self) -> Result<usize, HwCryptoError> {
320         match self {
321             MemoryBufferReferenceWithType::Input(buff_ref) => buff_ref.startOffset,
322             MemoryBufferReferenceWithType::Output(buff_ref) => buff_ref.startOffset,
323         }
324         .try_into()
325         .map_err(|e| {
326             hwcrypto_err!(BAD_PARAMETER, "buffer reference offsets cannot be negative: {:?}", e)
327         })
328     }
329 }
330 
331 /// Given a `MemoryBufferReference` it checks that its elements are valid (buffer_start should be
332 /// positive and buffer_size should be greater than 0) and then returns the memory reference
333 /// start/stop/size as an `usize` tuple
get_limits( buffer_reference: &MemoryBufferReferenceWithType, ) -> Result<(usize, usize, usize), HwCryptoError>334 fn get_limits(
335     buffer_reference: &MemoryBufferReferenceWithType,
336 ) -> Result<(usize, usize, usize), HwCryptoError> {
337     let buffer_size = buffer_reference.len()?;
338     let buffer_start = buffer_reference.start_offset()?;
339     if buffer_size == 0 {
340         return Err(hwcrypto_err!(BAD_PARAMETER, "buffer reference size shouldn't be 0"));
341     }
342     // Because both values are positive and originally signed, then the unsigned addition should not
343     // overflow. Using a checked add in case we can change these values to unsigned
344     // in the future
345     if let Some(buffer_end) = buffer_size.checked_add(buffer_start) {
346         Ok((buffer_start, buffer_end, buffer_size))
347     } else {
348         Err(hwcrypto_err!(BAD_PARAMETER, "buffer end overflowed"))
349     }
350 }
351 
352 // Wrapper over pointer used to map memory buffer.
353 struct MappedBuffer(NonNull<u8>);
354 
355 // SAFETY: `MappedBuffer` is only used to free object on drop or to create a `VolatileSlice` when
356 //         we need to access the underlying memory buffer; never directly. It is safe to access and
357 //         drop on a different thread. All accesses to the mmaped memory are done through the
358 //         `VolatileSlice` which already has the assumption that the underlying memory is shared
359 //         between different entities, so it only uses `std::ptr::{copy, read_volatile,
360 //         write_volatile}` to access memory.
361 unsafe impl Send for MappedBuffer {}
362 
363 struct MemoryBuffer {
364     buffer_ptr: MappedBuffer,
365     total_size: usize,
366 }
367 
368 impl MemoryBuffer {
new(memory_buffer_parameters: &MemoryBufferParameter) -> Result<Self, HwCryptoError>369     fn new(memory_buffer_parameters: &MemoryBufferParameter) -> Result<Self, HwCryptoError> {
370         if memory_buffer_parameters.sizeBytes <= 0 {
371             return Err(hwcrypto_err!(BAD_PARAMETER, "Buffer size was not greater than 0"));
372         }
373         // memory_buffer_parameters.size is positive and because it is an i32, conversion is correct
374         let buffer_size = memory_buffer_parameters.sizeBytes as u32;
375         let protection_flags = get_mmap_prot_flags(&memory_buffer_parameters.bufferHandle);
376         let buffer_handle = match &memory_buffer_parameters.bufferHandle {
377             MemoryBufferAidl::Input(handle) | MemoryBufferAidl::Output(handle) => handle,
378         };
379         let buffer_handle = buffer_handle
380             .as_ref()
381             .ok_or_else(|| hwcrypto_err!(BAD_PARAMETER, "received a null buffer handle"))?;
382         // SAFETY: mmap is left to choose the address for the allocation. It will check that the
383         //         protection flags, size and fd are correct and return a negative value if
384         //         not.
385         let buffer_ptr = unsafe {
386             trusty_sys::mmap(
387                 std::ptr::null_mut(),
388                 buffer_size,
389                 protection_flags,
390                 buffer_handle.as_ref().as_raw_fd(),
391             )
392         };
393         if trusty_sys::Error::is_ptr_err(buffer_ptr as *const c_void) {
394             return Err(hwcrypto_err!(
395                 BAD_PARAMETER,
396                 "mapping buffer handle failed: {}",
397                 buffer_ptr
398             ));
399         }
400         // cast is correct because buffer_ptr is positive and a pointer
401         let buffer_ptr = NonNull::new(buffer_ptr as *mut u8)
402             .ok_or(hwcrypto_err!(BAD_PARAMETER, "buffer_ptr was NULL"))?;
403         // cast is correct because buffer_size is an u32
404         let total_size = buffer_size as usize;
405 
406         Ok(Self { buffer_ptr: MappedBuffer(buffer_ptr), total_size })
407     }
408 
get_memory_slice<'a>(&'a mut self) -> Result<VolatileSlice<'a>, HwCryptoError>409     fn get_memory_slice<'a>(&'a mut self) -> Result<VolatileSlice<'a>, HwCryptoError> {
410         // SAFETY: Memory at address `buffer_ptr` has length `buffer_size` because if not mmap
411         //         operation would have failed. All accesses to this memory on this service are
412         //         through the VolatileSlice methods, so accesses are volatile accesses. Memory is
413         //         only unmapped on drop, so it will available for the lifetime of the
414         //         `VolatileSlice`.
415         let mem_buffer = unsafe { VolatileSlice::new(self.buffer_ptr.0.as_ptr(), self.total_size) };
416         Ok(mem_buffer)
417     }
418 
get_subslice_as_data_to_process<'a>( &'a mut self, start: usize, size: usize, ) -> Result<DataToProcess<'a>, HwCryptoError>419     fn get_subslice_as_data_to_process<'a>(
420         &'a mut self,
421         start: usize,
422         size: usize,
423     ) -> Result<DataToProcess<'a>, HwCryptoError> {
424         let mem_buffer = self.get_memory_slice()?;
425         Ok(DataToProcess::new_from_volatile_slice(mem_buffer.subslice(start, size)?))
426     }
427 }
428 
429 impl Drop for MemoryBuffer {
drop(&mut self)430     fn drop(&mut self) {
431         // SAFETY: `buffer_ptr` and `total_size` were set up and remain unchanged for the lifetime
432         //         of the object. `buffer_ptr` is still mapped at this point
433         unsafe {
434             trusty_sys::munmap(self.buffer_ptr.0.as_ptr().cast::<c_void>(), self.total_size as u32)
435         };
436     }
437 }
438 
439 // `CmdProcessorContext` is the type in charge of executing a set of commands.
440 pub(crate) struct CmdProcessorContext {
441     current_input_memory_buffer: Option<MemoryBuffer>,
442     current_output_memory_buffer: Option<MemoryBuffer>,
443     current_state: CmdProcessorState,
444     current_crypto_operation: Option<Box<dyn ICryptographicOperation>>,
445 }
446 
447 impl std::fmt::Debug for CmdProcessorContext {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result448     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
449         write!(
450             f,
451             "CmdProcessorContext {{ input buffer set: {}, output buffer set: {}, state: {:?} }}",
452             self.current_input_memory_buffer.is_some(),
453             self.current_output_memory_buffer.is_some(),
454             self.current_state
455         )
456     }
457 }
458 
459 impl CmdProcessorContext {
new() -> Self460     pub(crate) fn new() -> Self {
461         Self {
462             current_input_memory_buffer: None,
463             current_output_memory_buffer: None,
464             current_state: CmdProcessorState::InitialState,
465             current_crypto_operation: None,
466         }
467     }
468 
469     // Helper function used to check if a given `MemoryBufferReference` is valid for the active
470     // `MemoryBuffer`s of the state machine
check_memory_reference_in_range( &self, buffer_reference: &MemoryBufferReferenceWithType, ) -> Result<(), HwCryptoError>471     fn check_memory_reference_in_range(
472         &self,
473         buffer_reference: &MemoryBufferReferenceWithType,
474     ) -> Result<(), HwCryptoError> {
475         let current_memory_buffer = match buffer_reference {
476             MemoryBufferReferenceWithType::Input(_) => &self.current_input_memory_buffer,
477             MemoryBufferReferenceWithType::Output(_) => &self.current_output_memory_buffer,
478         };
479         let buffer_start = buffer_reference.start_offset()?;
480         let buffer_size = buffer_reference.len()?;
481         if buffer_size == 0 {
482             return Err(hwcrypto_err!(BAD_PARAMETER, "cannot create buffer references of size 0"));
483         }
484         if let Some(current_memory_buffer) = current_memory_buffer {
485             if buffer_start >= current_memory_buffer.total_size {
486                 return Err(hwcrypto_err!(BAD_PARAMETER, "buffer start falls outside of buffer"));
487             }
488             // Because both values are positive and signed, then the addition should not
489             // overflow. Using a checked add in case we can change these values to unsigned
490             // in the future
491             if let Some(buffer_end) = buffer_size.checked_add(buffer_start) {
492                 if buffer_end > current_memory_buffer.total_size {
493                     Err(hwcrypto_err!(BAD_PARAMETER, "buffer reference falls outside of buffer"))
494                 } else {
495                     Ok(())
496                 }
497             } else {
498                 Err(hwcrypto_err!(BAD_PARAMETER, "requested size goes past buffer end"))
499             }
500         } else {
501             Err(hwcrypto_err!(
502                 BAD_PARAMETER,
503                 "memory buffer has not been set yet, so we cannot process references to it"
504             ))
505         }
506     }
507 
get_data_buffer_size( &self, buffer_reference: &MemoryBufferReferenceWithType, ) -> Result<usize, HwCryptoError>508     fn get_data_buffer_size(
509         &self,
510         buffer_reference: &MemoryBufferReferenceWithType,
511     ) -> Result<usize, HwCryptoError> {
512         self.check_memory_reference_in_range(buffer_reference)?;
513         buffer_reference.len()
514     }
515 
set_memory_buffer_step( &mut self, parameters: &MemoryBufferParameter, current_output_ref: &mut Option<OutputData>, ) -> Result<(), HwCryptoError>516     fn set_memory_buffer_step(
517         &mut self,
518         parameters: &MemoryBufferParameter,
519         current_output_ref: &mut Option<OutputData>,
520     ) -> Result<(), HwCryptoError> {
521         let (current_memory_buffer, buffer_is_output) = match &parameters.bufferHandle {
522             MemoryBufferAidl::Input(_) => (&mut self.current_input_memory_buffer, false),
523             MemoryBufferAidl::Output(_) => (&mut self.current_output_memory_buffer, true),
524         };
525         if current_memory_buffer.is_some() {
526             Err(hwcrypto_err!(BAD_PARAMETER, "Memory buffer already set"))
527         } else {
528             if parameters.sizeBytes < 0 {
529                 Err(hwcrypto_err!(BAD_PARAMETER, "Memory buffer size is negative"))
530             } else {
531                 // With the current behaviour, next check should not be needed, because we can only
532                 // set up the current_memory_buffer once and we can only set the current_output_ref
533                 // after setting a current output memory buffer. Leaving the check here in case the
534                 // behavior changes in the future
535                 if buffer_is_output {
536                     if let Some(OutputData::MemoryReference(_, _)) = current_output_ref {
537                         // If the current output is a buffer reference, we need to invalidate it
538                         return Err(hwcrypto_err!(BAD_PARAMETER, "This should not be possible with current flow, we need to invalidate the current output reference now."));
539                     }
540                 }
541                 *current_memory_buffer = Some(MemoryBuffer::new(parameters)?);
542                 Ok(())
543             }
544         }
545     }
546 
add_output_step<'a>( &mut self, output_parameters: &'a mut OperationData, ) -> Result<OutputData<'a>, HwCryptoError>547     fn add_output_step<'a>(
548         &mut self,
549         output_parameters: &'a mut OperationData,
550     ) -> Result<OutputData<'a>, HwCryptoError> {
551         match output_parameters {
552             OperationData::DataBuffer(buf) => Ok(OutputData::DataBuffer(buf)),
553             OperationData::MemoryBufferReference(buffer_reference) => {
554                 Ok(OutputData::MemoryReference(
555                     *buffer_reference,
556                     self.get_data_buffer_size(&MemoryBufferReferenceWithType::Output(
557                         (*buffer_reference).into(),
558                     ))?,
559                 ))
560             }
561         }
562     }
563 
finish_step( &mut self, current_output_ref: &mut Option<OutputData>, ) -> Result<(), HwCryptoError>564     fn finish_step(
565         &mut self,
566         current_output_ref: &mut Option<OutputData>,
567     ) -> Result<(), HwCryptoError> {
568         self.operation_step(None, current_output_ref, true, None)?;
569         self.current_crypto_operation = None;
570         Ok(())
571     }
572 
input_step( &mut self, input_parameters: &mut OperationData, current_output_ref: &mut Option<OutputData>, ) -> Result<(), HwCryptoError>573     fn input_step(
574         &mut self,
575         input_parameters: &mut OperationData,
576         current_output_ref: &mut Option<OutputData>,
577     ) -> Result<(), HwCryptoError> {
578         self.operation_step(Some(input_parameters), current_output_ref, false, None)
579     }
580 
set_pattern(&mut self, step_parameter: &mut PatternParameters) -> Result<(), HwCryptoError>581     fn set_pattern(&mut self, step_parameter: &mut PatternParameters) -> Result<(), HwCryptoError> {
582         let crypto_operation = self
583             .current_crypto_operation
584             .as_mut()
585             .ok_or(hwcrypto_err!(BAD_PARAMETER, "crypto operation has not been set yet"))?;
586         crypto_operation.set_operation_pattern(step_parameter)
587     }
588 
operation_step( &mut self, input_parameters: Option<&mut OperationData>, current_output_ref: &mut Option<OutputData>, is_finish: bool, operation_impl: Option<&mut dyn ICryptographicOperation>, ) -> Result<(), HwCryptoError>589     fn operation_step(
590         &mut self,
591         input_parameters: Option<&mut OperationData>,
592         current_output_ref: &mut Option<OutputData>,
593         is_finish: bool,
594         operation_impl: Option<&mut dyn ICryptographicOperation>,
595     ) -> Result<(), HwCryptoError> {
596         // Doing this check here to keep the borrow checker happy because the next step borrows self
597         // mutably. This is because even though it is an input, if it is a buffer reference, the
598         // available method could potentially be use to modify the underlying memory buffer.
599         if let Some(OutputData::MemoryReference(buff_ref, _)) = current_output_ref.as_ref() {
600             self.check_memory_reference_in_range(&MemoryBufferReferenceWithType::Output(
601                 (*buff_ref).into(),
602             ))?;
603         }
604         // Creating a `DataToProcess` variable to abstract away where the input is located
605         let mut input = match input_parameters {
606             Some(OperationData::MemoryBufferReference(buffer_reference)) => Some({
607                 let buffer_reference =
608                     MemoryBufferReferenceWithType::Input((*buffer_reference).into());
609                 self.check_memory_reference_in_range(&buffer_reference)?;
610                 let (input_start, _input_stop, input_size) = get_limits(&buffer_reference)?;
611                 self.current_input_memory_buffer
612                     .as_mut()
613                     .ok_or(hwcrypto_err!(BAD_PARAMETER, "input buffer not set yet"))?
614                     .get_subslice_as_data_to_process(input_start, input_size)?
615             }),
616             Some(OperationData::DataBuffer(input)) => {
617                 Some(DataToProcess::new_from_slice(&mut input[..]))
618             }
619             None => None,
620         };
621         if let Some(ref input) = input {
622             if input.len() == 0 {
623                 return Err(hwcrypto_err!(BAD_PARAMETER, "received an input of size 0"));
624             }
625         }
626         let crypto_operation: &mut dyn ICryptographicOperation =
627             operation_impl.ok_or(()).or_else(|_| {
628                 let crypto_operation = self
629                     .current_crypto_operation
630                     .as_mut()
631                     .ok_or(hwcrypto_err!(BAD_PARAMETER, "crypto operation has not been set yet"))?;
632                 if !crypto_operation.is_active() {
633                     return Err(hwcrypto_err!(BAD_PARAMETER, "operation is not active"));
634                 }
635                 Ok(&mut **crypto_operation)
636             })?;
637         let req_output_size = crypto_operation.get_operation_req_size(input.as_ref(), is_finish)?;
638 
639         // Getting a reference to the output for the copy operation
640         match current_output_ref
641             .as_mut()
642             .ok_or(hwcrypto_err!(BAD_PARAMETER, "no output buffer available"))?
643         {
644             OutputData::DataBuffer(output_vec) => {
645                 // We are saving data into a vector, as long as we can resize the vector we can fit
646                 // the result
647                 let original_size = output_vec.len();
648                 let mut output_buff =
649                     DataToProcess::allocate_buffer_end_vector(*output_vec, req_output_size)?;
650                 let added_bytes =
651                     crypto_operation.operation(input.as_mut(), &mut output_buff, is_finish)?;
652                 output_vec.truncate(original_size + added_bytes);
653             }
654             OutputData::MemoryReference(output_buff_ref, remaining_size) => {
655                 if req_output_size > *remaining_size {
656                     return Err(hwcrypto_err!(ALLOCATION_ERROR, "run out of space output buffer"));
657                 }
658                 let (_output_start, output_stop, _output_size) =
659                     get_limits(&MemoryBufferReferenceWithType::Output((*output_buff_ref).into()))?;
660                 // We are automatically filling up the output buffer with the received input, so
661                 // the first available position will be equal to the end of the buffer minus the
662                 // remaining space:
663                 //
664                 //         |---------------------_output_size------------------------------|
665                 //         |--------used space--------|----------remaining_size------------|
666                 //         |xxxxxxxxxxxxxxxxxxxxxxxxxx|====================================|
667                 // _output_start                output_start_offset                    output_stop
668                 //
669                 let output_start_offset = output_stop - *remaining_size;
670                 let mut output_slice = self
671                     .current_output_memory_buffer
672                     .as_mut()
673                     .ok_or(hwcrypto_err!(BAD_PARAMETER, "output buffer not set yet"))?
674                     .get_subslice_as_data_to_process(output_start_offset, req_output_size)?;
675                 let req_output_size =
676                     crypto_operation.operation(input.as_mut(), &mut output_slice, is_finish)?;
677                 *remaining_size = *remaining_size - req_output_size;
678             }
679         }
680         Ok(())
681     }
682 
copy_step( &mut self, copy_parameters: &mut OperationData, current_output_ref: &mut Option<OutputData>, ) -> Result<(), HwCryptoError>683     fn copy_step(
684         &mut self,
685         copy_parameters: &mut OperationData,
686         current_output_ref: &mut Option<OutputData>,
687     ) -> Result<(), HwCryptoError> {
688         self.operation_step(
689             Some(copy_parameters),
690             current_output_ref,
691             false,
692             Some(&mut CopyOperation),
693         )
694     }
695 
destroy_step( &mut self, current_output_ref: &mut Option<OutputData>, ) -> Result<(), HwCryptoError>696     fn destroy_step(
697         &mut self,
698         current_output_ref: &mut Option<OutputData>,
699     ) -> Result<(), HwCryptoError> {
700         self.current_input_memory_buffer = None;
701         self.current_output_memory_buffer = None;
702         self.current_crypto_operation = None;
703         *current_output_ref = None;
704         self.current_state = CmdProcessorState::Destroyed;
705         Ok(())
706     }
707 
is_destroyed(&self) -> bool708     pub(crate) fn is_destroyed(&self) -> bool {
709         self.current_state == CmdProcessorState::Destroyed
710     }
711 
set_operation_parameters_step( &mut self, crypto_operation_parameters: &OperationParameters, _current_output_ref: &mut Option<OutputData>, ) -> Result<(), HwCryptoError>712     fn set_operation_parameters_step(
713         &mut self,
714         crypto_operation_parameters: &OperationParameters,
715         _current_output_ref: &mut Option<OutputData>,
716     ) -> Result<(), HwCryptoError> {
717         let crypto_operation = CryptographicOperation::new_binder(crypto_operation_parameters)?;
718         self.current_crypto_operation = Some(crypto_operation);
719         Ok(())
720     }
721 
process_all_steps( &mut self, operations: &mut [CryptoOperation], ) -> Result<(), HwCryptoError>722     pub(crate) fn process_all_steps(
723         &mut self,
724         operations: &mut [CryptoOperation],
725     ) -> Result<(), HwCryptoError> {
726         if operations.is_empty() {
727             return Err(hwcrypto_err!(BAD_PARAMETER, "Cannot process list of length 0",));
728         }
729         let mut curr_output: Option<OutputData> = None;
730         for current_step in operations {
731             match self.current_state {
732                 CmdProcessorState::InitialState => match current_step {
733                     CryptoOperation::DataOutput(step_data) => {
734                         curr_output = Some(self.add_output_step(step_data)?);
735                     }
736                     CryptoOperation::CopyData(step_data) => {
737                         self.copy_step(step_data, &mut curr_output)?;
738                     }
739                     CryptoOperation::DestroyContext(_) => self.destroy_step(&mut curr_output)?,
740                     CryptoOperation::SetMemoryBuffer(step_data) => {
741                         self.set_memory_buffer_step(&step_data, &mut curr_output)?
742                     }
743                     CryptoOperation::SetOperationParameters(step_data) => {
744                         self.current_state = CmdProcessorState::RunningOperation;
745                         self.set_operation_parameters_step(&step_data, &mut curr_output)?;
746                     }
747                     CryptoOperation::SetPattern(_) => {
748                         return Err(hwcrypto_err!(
749                             BAD_PARAMETER,
750                             "SetPattern not permitted before calling SetOperationParameters"
751                         ))
752                     }
753                     CryptoOperation::DataInput(_) => {
754                         return Err(hwcrypto_err!(
755                             BAD_PARAMETER,
756                             "DataInput not permitted before calling SetOperationParameters"
757                         ))
758                     }
759                     CryptoOperation::AadInput(_) => {
760                         return Err(hwcrypto_err!(
761                             BAD_PARAMETER,
762                             "AadInput not permitted before calling SetOperationParameters"
763                         ))
764                     }
765                     CryptoOperation::Finish(_) => {
766                         return Err(hwcrypto_err!(
767                             BAD_PARAMETER,
768                             "Finish not permitted before calling SetOperationParameters"
769                         ))
770                     }
771                 },
772                 CmdProcessorState::RunningOperation => match current_step {
773                     CryptoOperation::DataOutput(step_data) => {
774                         curr_output = Some(self.add_output_step(step_data)?);
775                     }
776                     CryptoOperation::CopyData(step_data) => {
777                         self.copy_step(step_data, &mut curr_output)?;
778                     }
779                     CryptoOperation::DestroyContext(_) => self.destroy_step(&mut curr_output)?,
780                     CryptoOperation::Finish(_step_data) => {
781                         self.current_state = CmdProcessorState::InitialState;
782                         self.finish_step(&mut curr_output)?;
783                     }
784                     CryptoOperation::SetPattern(step_data) => {
785                         self.set_pattern(step_data)?;
786                     }
787                     CryptoOperation::DataInput(step_data) => {
788                         self.input_step(step_data, &mut curr_output)?;
789                     }
790                     CryptoOperation::AadInput(_) => unimplemented!("AadInput not implemented yet"),
791                     CryptoOperation::SetOperationParameters(_step) => unimplemented!(
792                         "SetOperationParameters from RunningOperation not implemented yet"
793                     ),
794                     CryptoOperation::SetMemoryBuffer(_) => {
795                         return Err(hwcrypto_err!(
796                         BAD_PARAMETER,
797                         "SetMemoryBuffer not permitted once SetOperationParameters has been called"
798                     ))
799                     }
800                 },
801                 CmdProcessorState::Destroyed => {
802                     return Err(hwcrypto_err!(
803                         BAD_PARAMETER,
804                         "Cannot send any command after DestroyContext"
805                     ));
806                 }
807             }
808         }
809         Ok(())
810     }
811 }
812 
813 #[cfg(test)]
814 mod tests {
815     use super::*;
816     use crate::opaque_key::OpaqueKey;
817     use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{
818         types::{
819             AesCipherMode::AesCipherMode, CipherModeParameters::CipherModeParameters, HalErrorCode,
820             KeyLifetime::KeyLifetime, KeyType::KeyType, KeyUse::KeyUse,
821             SymmetricCryptoParameters::SymmetricCryptoParameters,
822             SymmetricOperation::SymmetricOperation,
823             SymmetricOperationParameters::SymmetricOperationParameters,
824         },
825         KeyPolicy::KeyPolicy,
826         OperationParameters::OperationParameters,
827         PatternParameters::PatternParameters,
828     };
829     use binder::ParcelFileDescriptor;
830     use core::ffi::c_void;
831     use std::alloc::{alloc_zeroed, dealloc, Layout};
832     use std::os::fd::{FromRawFd, OwnedFd};
833     use test::{expect, expect_eq};
834     use tipc::Uuid;
835 
connection_info() -> Uuid836     fn connection_info() -> Uuid {
837         // TODO: This is a temporary mock function for testing until we move to use DICE policies.
838         Uuid::new_from_string("f41a7796-975a-4279-8cc4-b73f8820430d").unwrap()
839     }
840     /// Structure only intended to use on unit tests. It will allocate a single memory page and
841     /// create a memref to it.
842     struct TestPageAllocator {
843         allocated_buffer: *mut u8,
844         layout: Layout,
845         raw_trusty_fd: i64,
846         parcel_file_descriptor_created: bool,
847     }
848 
849     impl TestPageAllocator {
new() -> Result<Self, HwCryptoError>850         fn new() -> Result<Self, HwCryptoError> {
851             let page_size = Self::get_allocation_size();
852             if page_size == 0 {
853                 return Err(hwcrypto_err!(ALLOCATION_ERROR, "received zero as the page size"));
854             }
855             let layout = Layout::from_size_align(page_size, page_size).map_err(|e| {
856                 hwcrypto_err!(
857                     GENERIC_ERROR,
858                     "layout creation error, should not have happened: {:?}",
859                     e
860                 )
861             })?;
862             // SAFETY: Layout is non-zero
863             let allocated_buffer = unsafe {
864                 let ptr = alloc_zeroed(layout);
865                 ptr
866             };
867             // Always mapping things as output to change the buffer values for tests
868             let prot_flags = OUTPUT_MEMORY_BUFFER_FLAGS;
869             // SAFETY: address and size are correct because they came from the allocation.
870             let raw_trusty_fd = unsafe {
871                 trusty_sys::memref_create(
872                     allocated_buffer as *mut c_void,
873                     page_size as u32,
874                     prot_flags,
875                 )
876             };
877             if raw_trusty_fd < 0 {
878                 return Err(hwcrypto_err!(ALLOCATION_ERROR, "memref creation failed"));
879             }
880             let parcel_file_descriptor_created = false;
881             Ok(Self {
882                 allocated_buffer,
883                 layout,
884                 raw_trusty_fd: raw_trusty_fd.into(),
885                 parcel_file_descriptor_created,
886             })
887         }
888 
get_parcel_file_descriptor(&mut self) -> Result<ParcelFileDescriptor, HwCryptoError>889         fn get_parcel_file_descriptor(&mut self) -> Result<ParcelFileDescriptor, HwCryptoError> {
890             if self.parcel_file_descriptor_created {
891                 return Err(hwcrypto_err!(
892                     GENERIC_ERROR,
893                     "only a single parcel file descriptor can be created"
894                 ));
895             }
896             // fd is valid if the object has been created and we can take ownership of it.
897             self.parcel_file_descriptor_created = true;
898             let fd = unsafe { OwnedFd::from_raw_fd(self.raw_trusty_fd as i32) };
899             Ok(ParcelFileDescriptor::new(fd))
900         }
901 
get_allocation_size() -> usize902         fn get_allocation_size() -> usize {
903             // SAFETY: FFI call with all safe arguments.
904             let page_size = unsafe { libc::getauxval(libc::AT_PAGESZ) };
905             page_size as usize
906         }
907 
copy_values(&mut self, start: usize, values: &[u8]) -> Result<(), HwCryptoError>908         fn copy_values(&mut self, start: usize, values: &[u8]) -> Result<(), HwCryptoError> {
909             if self.parcel_file_descriptor_created {
910                 // There is already another reference to this memory area, don't allow to change it
911                 // anymore through this method
912                 return Err(hwcrypto_err!(GENERIC_ERROR, "copy_values is meant for initialization before creating any other references to this memory area"));
913             }
914             if start + values.len() > Self::get_allocation_size() {
915                 return Err(hwcrypto_err!(BAD_PARAMETER, "input won't fit in buffer"));
916             }
917             // SAFETY: - value is valid for all the range that is read
918             //         - allocated_buffer[start, start + values.len()] is a valid area to write
919             //         - allocated_buffer and values are properly aligned because they are `u8`
920             //         - both areas do not overlap because allocated_buffer is a newly allocated
921             //           buffer and we do not have methods to get references to this area until
922             //           after this method is no longer valid.
923             unsafe {
924                 self.allocated_buffer
925                     .wrapping_add(start)
926                     .copy_from_nonoverlapping(values.as_ptr(), values.len());
927             }
928             Ok(())
929         }
930     }
931 
932     impl Drop for TestPageAllocator {
drop(&mut self)933         fn drop(&mut self) {
934             // SAFETY: `allocated_buffer` is valid and have been allocated by the same allocator.
935             //         layout was stored at allocation time, so it matches.
936             unsafe { dealloc(self.allocated_buffer, self.layout) };
937         }
938     }
939 
read_slice( memory_buffer: &MemoryBuffer, buf: &mut [u8], start: usize, ) -> Result<(), HwCryptoError>940     fn read_slice(
941         memory_buffer: &MemoryBuffer,
942         buf: &mut [u8],
943         start: usize,
944     ) -> Result<(), HwCryptoError> {
945         // SAFETY: Memory at address `buffer_ptr` has length `buffer_size` because if not mmap
946         //         operation would have failed. All accesses to this memory on this service are
947         //         through the VolatileSlice methods, so accesses are volatile accesses. Memory
948         //         is only unmapped on drop, so it will available for the lifetime of the
949         //         `VolatileSlice`.
950         let mem_buffer = unsafe {
951             VolatileSlice::new(memory_buffer.buffer_ptr.0.as_ptr(), memory_buffer.total_size)
952         };
953         mem_buffer.read_slice(buf, start).map_err(HwCryptoError::from)
954     }
955 
write_slice( memory_buffer: &mut MemoryBuffer, buf: &[u8], start: usize, ) -> Result<(), HwCryptoError>956     fn write_slice(
957         memory_buffer: &mut MemoryBuffer,
958         buf: &[u8],
959         start: usize,
960     ) -> Result<(), HwCryptoError> {
961         let mem_buffer = memory_buffer.get_memory_slice()?;
962         Ok(mem_buffer.write_slice(buf, start)?)
963     }
964 
965     #[test]
create_memory_buffer()966     fn create_memory_buffer() {
967         let mut output_page = TestPageAllocator::new().expect("couldn't allocate test page");
968         output_page.copy_values(0, &[1, 2, 3, 4, 5, 6, 7, 8, 9]).unwrap();
969 
970         let total_buffer_size = TestPageAllocator::get_allocation_size();
971         let mem_buffer_parameters = MemoryBufferParameter {
972             bufferHandle: MemoryBufferAidl::Output(Some(
973                 output_page.get_parcel_file_descriptor().expect("couldn't create fd"),
974             )),
975             sizeBytes: total_buffer_size as i32,
976         };
977         let mut memory_buffer =
978             MemoryBuffer::new(&mem_buffer_parameters).expect("Couldn't createa memory buffer");
979 
980         let mut slice = vec![0; 5];
981 
982         read_slice(&memory_buffer, &mut slice[0..2], 1).expect("couldn't get slice");
983         expect_eq!(&slice[0..2], &[2, 3], "wrong value retrieved through slice");
984 
985         read_slice(&memory_buffer, &mut slice[0..1], 8).expect("couldn't get slice");
986         expect_eq!(&slice[0..1], &[9], "wrong value retrieved through slice");
987 
988         let result = read_slice(&memory_buffer, &mut slice[0..2], total_buffer_size - 1);
989         expect!(result.is_err(), "Shouldn't be able to get slice with end out of range");
990 
991         let result = read_slice(&memory_buffer, &mut slice[0..1], total_buffer_size);
992         expect!(result.is_err(), "Shouldn't be able to get slice with start out of range");
993 
994         read_slice(&memory_buffer, &mut slice[0..1], 0).expect("couldn't get slice");
995         expect_eq!(&slice[0..1], &[1], "wrong value retrieved through slice");
996 
997         read_slice(&memory_buffer, &mut slice[0..3], 4).expect("couldn't get slice");
998         expect_eq!(&slice[0..3], &[5, 6, 7], "wrong value retrieved through slice");
999 
1000         write_slice(&mut memory_buffer, &[55], 5).expect("couldn't write slice");
1001         read_slice(&memory_buffer, &mut slice[0..3], 4).expect("couldn't get slice");
1002         expect_eq!(&slice[0..3], &[5, 55, 7], "wrong value retrieved through slice");
1003 
1004         read_slice(&memory_buffer, &mut slice[0..5], 3).expect("couldn't get slice");
1005         expect_eq!(&slice[0..5], &[4, 5, 55, 7, 8], "wrong value retrieved through slice");
1006     }
1007 
1008     #[test]
create_output_data_references()1009     fn create_output_data_references() {
1010         let mut output_page = TestPageAllocator::new().expect("couldn't allocate test page");
1011         let total_buffer_size = TestPageAllocator::get_allocation_size();
1012         let mem_buffer_parameters = MemoryBufferParameter {
1013             bufferHandle: MemoryBufferAidl::Output(Some(
1014                 output_page.get_parcel_file_descriptor().expect("couldn't create fd"),
1015             )),
1016             sizeBytes: total_buffer_size as i32,
1017         };
1018 
1019         let mut cmd_list = Vec::<CryptoOperation>::new();
1020         let mut cmd_processor = CmdProcessorContext::new();
1021 
1022         cmd_list.push(CryptoOperation::SetMemoryBuffer(mem_buffer_parameters));
1023         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1024         expect!(process_result.is_ok(), "Couldn't process SetMemoryBuffer command");
1025         let mem_reference = MemoryBufferReference { startOffset: 0, sizeBytes: 3 };
1026         cmd_list
1027             .push(CryptoOperation::DataOutput(OperationData::MemoryBufferReference(mem_reference)));
1028 
1029         let mut cmd_processor = CmdProcessorContext::new();
1030         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1031         expect!(process_result.is_ok(), "Couldn't process valid memory reference");
1032 
1033         let mem_ref = MemoryBufferReference { startOffset: total_buffer_size as i32, sizeBytes: 1 };
1034         cmd_list[1] = CryptoOperation::DataOutput(OperationData::MemoryBufferReference(mem_ref));
1035         let mut cmd_processor = CmdProcessorContext::new();
1036         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1037         expect!(
1038             process_result.is_err(),
1039             "Shouldn't be able to process reference outside of buffer"
1040         );
1041 
1042         let mem_ref = MemoryBufferReference { startOffset: total_buffer_size as i32, sizeBytes: 0 };
1043         cmd_list[1] = CryptoOperation::DataOutput(OperationData::MemoryBufferReference(mem_ref));
1044         let mut cmd_processor = CmdProcessorContext::new();
1045         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1046         expect!(
1047             process_result.is_err(),
1048             "Shouldn't be able to process reference outside of buffer"
1049         );
1050 
1051         let mem_ref = MemoryBufferReference { startOffset: 3, sizeBytes: 0 };
1052         cmd_list[1] = CryptoOperation::DataOutput(OperationData::MemoryBufferReference(mem_ref));
1053         let mut cmd_processor = CmdProcessorContext::new();
1054         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1055         expect!(process_result.is_err(), "Shouldn't be able to process 0 size references");
1056 
1057         let mem_ref =
1058             MemoryBufferReference { startOffset: total_buffer_size as i32 - 1, sizeBytes: 1 };
1059         cmd_list[1] = CryptoOperation::DataOutput(OperationData::MemoryBufferReference(mem_ref));
1060         let mut cmd_processor = CmdProcessorContext::new();
1061         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1062         expect!(
1063             process_result.is_ok(),
1064             "Couldn't process a valid memory reference, len {}",
1065             cmd_list.len()
1066         );
1067 
1068         let mem_ref =
1069             MemoryBufferReference { startOffset: total_buffer_size as i32 - 1, sizeBytes: 2 };
1070         cmd_list[1] = CryptoOperation::DataOutput(OperationData::MemoryBufferReference(mem_ref));
1071         let mut cmd_processor = CmdProcessorContext::new();
1072         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1073         expect!(
1074             process_result.is_err(),
1075             "Shouldn't be able to process reference that falls out of range"
1076         );
1077     }
1078 
1079     #[test]
parse_empty_cmd_list()1080     fn parse_empty_cmd_list() {
1081         let mut cmd_list = Vec::<CryptoOperation>::new();
1082         let mut cmd_processor = CmdProcessorContext::new();
1083 
1084         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1085         match &process_result {
1086             Err(e) => expect!(
1087                 e.matches_hal_error_code(HalErrorCode::BAD_PARAMETER),
1088                 "should have received a BAD_PARAMETER error"
1089             ),
1090             Ok(_) => expect!(process_result.is_err(), "Should have received an error"),
1091         };
1092 
1093         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1094         match &process_result {
1095             Err(e) => expect!(
1096                 e.matches_hal_error_code(HalErrorCode::BAD_PARAMETER),
1097                 "should have received a BAD_PARAMETER error"
1098             ),
1099             Ok(_) => expect!(process_result.is_err(), "Should have received an error"),
1100         };
1101     }
1102 
1103     #[test]
parse_cmd_list_single_item()1104     fn parse_cmd_list_single_item() {
1105         let mut cmd_list = Vec::<CryptoOperation>::new();
1106         let mut cmd_processor = CmdProcessorContext::new();
1107         let data_output = OperationData::DataBuffer(Vec::new());
1108         cmd_list.push(CryptoOperation::DataOutput(data_output));
1109         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1110         expect!(process_result.is_ok(), "Couldn't process command");
1111     }
1112 
1113     #[test]
invalid_operations_initial_state()1114     fn invalid_operations_initial_state() {
1115         let mut cmd_list = Vec::<CryptoOperation>::new();
1116         let mut cmd_processor = CmdProcessorContext::new();
1117         cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(Vec::new())));
1118         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1119         expect!(process_result.is_err(), "Shouldn't be able to call DataInput on initial state");
1120         let mut cmd_list = Vec::<CryptoOperation>::new();
1121         let mut cmd_processor = CmdProcessorContext::new();
1122         cmd_list.push(CryptoOperation::AadInput(OperationData::DataBuffer(Vec::new())));
1123 
1124         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1125         expect!(process_result.is_err(), "Shouldn't be able to call AadInput on initial state");
1126         let mut cmd_list = Vec::<CryptoOperation>::new();
1127         let mut cmd_processor = CmdProcessorContext::new();
1128         let pattern_params = PatternParameters { numberBlocksProcess: 1, numberBlocksCopy: 9 };
1129         cmd_list.push(CryptoOperation::SetPattern(pattern_params));
1130         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1131         expect!(process_result.is_err(), "Shouldn't be able to call SetPattern on initial state");
1132         let mut cmd_list = Vec::<CryptoOperation>::new();
1133         let mut cmd_processor = CmdProcessorContext::new();
1134         cmd_list.push(CryptoOperation::Finish(None));
1135         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1136         expect!(process_result.is_err(), "Shouldn't be able to call Finish on initial state");
1137         let mut cmd_list = Vec::<CryptoOperation>::new();
1138         let mut cmd_processor = CmdProcessorContext::new();
1139         cmd_list.push(CryptoOperation::DataOutput(OperationData::DataBuffer(Vec::new())));
1140         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1141         expect!(process_result.is_ok(), "Should be able to call DataOutput");
1142     }
1143 
1144     #[test]
invalid_operations_destroyed_state()1145     fn invalid_operations_destroyed_state() {
1146         let mut cmd_list = Vec::<CryptoOperation>::new();
1147         let mut cmd_processor = CmdProcessorContext::new();
1148         cmd_list.push(CryptoOperation::DestroyContext(None));
1149         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1150         expect!(process_result.is_ok(), "Should be able to call DestroyContext");
1151         let mut cmd_processor = CmdProcessorContext::new();
1152         cmd_list.push(CryptoOperation::DataOutput(OperationData::DataBuffer(Vec::new())));
1153         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1154         expect!(process_result.is_err(), "Shouldn't be able to call DataOutput on destroyed state");
1155         let mut cmd_processor = CmdProcessorContext::new();
1156         cmd_list[1] = CryptoOperation::DataInput(OperationData::DataBuffer(Vec::new()));
1157         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1158         expect!(process_result.is_err(), "Shouldn't be able to call DataInput on destroyed state");
1159         let mut cmd_processor = CmdProcessorContext::new();
1160         cmd_list[1] = CryptoOperation::AadInput(OperationData::DataBuffer(Vec::new()));
1161         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1162         expect!(process_result.is_err(), "Shouldn't be able to call AadInput on destroyed state");
1163         let pattern_params = PatternParameters { numberBlocksProcess: 1, numberBlocksCopy: 9 };
1164         cmd_list[1] = CryptoOperation::SetPattern(pattern_params);
1165         let mut cmd_processor = CmdProcessorContext::new();
1166         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1167         expect!(process_result.is_err(), "Shouldn't be able to call SetPattern on destroyed state");
1168         cmd_list[1] = CryptoOperation::Finish(None);
1169         let mut cmd_processor = CmdProcessorContext::new();
1170         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1171         expect!(process_result.is_err(), "Shouldn't be able to call Finish on destroyed state");
1172         let policy = KeyPolicy {
1173             usage: KeyUse::SIGN,
1174             keyLifetime: KeyLifetime::EPHEMERAL,
1175             keyPermissions: Vec::new(),
1176             keyType: KeyType::AES_128_CBC_NO_PADDING,
1177             keyManagementKey: false,
1178         };
1179         let key = OpaqueKey::generate_opaque_key(&policy, connection_info());
1180         expect!(key.is_ok(), "couldn't generate key");
1181         let key = key.unwrap();
1182         let mode = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1183             nonce: [0; 16],
1184         }));
1185         let op_parameters = SymmetricOperationParameters {
1186             key: Some(key),
1187             direction: SymmetricOperation::ENCRYPT,
1188             parameters: mode,
1189         };
1190         cmd_list[1] = CryptoOperation::SetOperationParameters(
1191             OperationParameters::SymmetricCrypto(op_parameters),
1192         );
1193         let mut cmd_processor = CmdProcessorContext::new();
1194         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1195         expect!(
1196             process_result.is_err(),
1197             "Shouldn't be able to call SetOperationParameters on destroyed state"
1198         );
1199     }
1200 
1201     #[test]
check_output_step_length()1202     fn check_output_step_length() {
1203         let alloc_size = TestPageAllocator::get_allocation_size();
1204         let mut output_page = TestPageAllocator::new().expect("couldn't create test page");
1205         let output_memory_buffer = MemoryBufferParameter {
1206             bufferHandle: MemoryBufferAidl::Output(Some(
1207                 output_page.get_parcel_file_descriptor().expect("couldn't get fd"),
1208             )),
1209             sizeBytes: alloc_size as i32,
1210         };
1211         let mut cmd_list = Vec::<CryptoOperation>::new();
1212         let mut cmd_processor = CmdProcessorContext::new();
1213         cmd_list.push(CryptoOperation::SetMemoryBuffer(output_memory_buffer));
1214         let output_reference = MemoryBufferReference { startOffset: 0, sizeBytes: 3 };
1215         cmd_list.push(CryptoOperation::DataOutput(OperationData::MemoryBufferReference(
1216             output_reference,
1217         )));
1218         cmd_list.push(CryptoOperation::CopyData(OperationData::DataBuffer(vec![1, 2, 3])));
1219         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1220         expect!(process_result.is_ok(), "Couldn't process command");
1221         let mut read_slice_val = vec![55; 9];
1222         let mem_buffer = cmd_processor.current_output_memory_buffer.as_ref().unwrap();
1223         read_slice(&mem_buffer, &mut read_slice_val[..], 0).unwrap();
1224         expect_eq!(
1225             &read_slice_val[..],
1226             &[1, 2, 3, 0, 0, 0, 0, 0, 0],
1227             "unexpected values after copy"
1228         );
1229 
1230         cmd_list.push(CryptoOperation::CopyData(OperationData::DataBuffer(vec![4, 5, 6])));
1231         let mut cmd_processor = CmdProcessorContext::new();
1232         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1233         expect!(
1234             process_result.is_err(),
1235             "Command should have failed because we run out of output buffer"
1236         );
1237         let mem_buffer = cmd_processor.current_output_memory_buffer.as_ref().unwrap();
1238         read_slice(&mem_buffer, &mut read_slice_val[..], 0).unwrap();
1239         expect_eq!(
1240             &read_slice_val[..],
1241             &[1, 2, 3, 0, 0, 0, 0, 0, 0],
1242             "unexpected values after failed copy"
1243         );
1244     }
1245 
1246     #[test]
output_step_out_range()1247     fn output_step_out_range() {
1248         let alloc_size = TestPageAllocator::get_allocation_size();
1249         let mut output_page = TestPageAllocator::new().expect("couldn't get test page");
1250         let output_memory_buffer = MemoryBufferParameter {
1251             bufferHandle: MemoryBufferAidl::Output(Some(
1252                 output_page.get_parcel_file_descriptor().expect("couldn't get fd"),
1253             )),
1254             sizeBytes: alloc_size as i32,
1255         };
1256         let mut input_page = TestPageAllocator::new().expect("couldn't get test page");
1257         let input_memory_buffer = MemoryBufferParameter {
1258             bufferHandle: MemoryBufferAidl::Input(Some(
1259                 input_page.get_parcel_file_descriptor().expect("couldn't get fd"),
1260             )),
1261             sizeBytes: alloc_size as i32,
1262         };
1263         let mut cmd_list = Vec::<CryptoOperation>::new();
1264         let mut cmd_processor = CmdProcessorContext::new();
1265         cmd_list.push(CryptoOperation::SetMemoryBuffer(output_memory_buffer));
1266         cmd_list.push(CryptoOperation::SetMemoryBuffer(input_memory_buffer));
1267         let output_reference =
1268             MemoryBufferReference { startOffset: 0, sizeBytes: (alloc_size + 4) as i32 };
1269         cmd_list.push(CryptoOperation::DataOutput(OperationData::MemoryBufferReference(
1270             output_reference,
1271         )));
1272         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1273         expect!(process_result.is_err(), "shouldn't be able to add an output outside of range");
1274         let output_reference =
1275             MemoryBufferReference { startOffset: 0, sizeBytes: alloc_size as i32 };
1276         cmd_list[2] =
1277             CryptoOperation::DataOutput(OperationData::MemoryBufferReference(output_reference));
1278         let input_reference =
1279             MemoryBufferReference { startOffset: 0, sizeBytes: (alloc_size + 4) as i32 };
1280         cmd_list
1281             .push(CryptoOperation::CopyData(OperationData::MemoryBufferReference(input_reference)));
1282         let mut cmd_processor = CmdProcessorContext::new();
1283         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1284         expect!(process_result.is_err(), "shouldn't be able to add an input ref outside of range");
1285         let input_reference =
1286             MemoryBufferReference { startOffset: 0, sizeBytes: alloc_size as i32 };
1287         cmd_list[3] =
1288             CryptoOperation::CopyData(OperationData::MemoryBufferReference(input_reference));
1289         let mut cmd_processor = CmdProcessorContext::new();
1290         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1291         expect!(process_result.is_ok(), "operation should have succeeded");
1292     }
1293 
1294     #[test]
memory_reference_copy_operation_on_initial_state()1295     fn memory_reference_copy_operation_on_initial_state() {
1296         let alloc_size = TestPageAllocator::get_allocation_size();
1297         let mut output_page = TestPageAllocator::new().expect("couldn't get test page");
1298         let output_memory_buffer = MemoryBufferParameter {
1299             bufferHandle: MemoryBufferAidl::Output(Some(
1300                 output_page.get_parcel_file_descriptor().expect("couldn't get fd"),
1301             )),
1302             sizeBytes: alloc_size as i32,
1303         };
1304         let mut input_page = TestPageAllocator::new().expect("couldn't get test page");
1305         input_page.copy_values(0, &[7, 8, 9]).unwrap();
1306         let input_memory_buffer = MemoryBufferParameter {
1307             bufferHandle: MemoryBufferAidl::Input(Some(
1308                 input_page.get_parcel_file_descriptor().expect("couldn't get fd"),
1309             )),
1310             sizeBytes: alloc_size as i32,
1311         };
1312         let mut cmd_list = Vec::<CryptoOperation>::new();
1313         let mut cmd_processor = CmdProcessorContext::new();
1314         cmd_list.push(CryptoOperation::SetMemoryBuffer(output_memory_buffer));
1315         cmd_list.push(CryptoOperation::SetMemoryBuffer(input_memory_buffer));
1316         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1317         expect!(process_result.is_ok(), "Couldn't process command");
1318         let mut read_slice_val = vec![55; 9];
1319         let mem_buffer = cmd_processor.current_output_memory_buffer.as_ref().unwrap();
1320         read_slice(&mem_buffer, &mut read_slice_val[..], 0).unwrap();
1321         expect_eq!(&read_slice_val[..], &[0, 0, 0, 0, 0, 0, 0, 0, 0], "initial values where not 0");
1322         let mut cmd_processor = CmdProcessorContext::new();
1323         let output_reference =
1324             MemoryBufferReference { startOffset: 0, sizeBytes: alloc_size as i32 };
1325         cmd_list.push(CryptoOperation::DataOutput(OperationData::MemoryBufferReference(
1326             output_reference,
1327         )));
1328         cmd_list.push(CryptoOperation::CopyData(OperationData::DataBuffer(vec![1, 2, 3])));
1329         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1330         expect!(process_result.is_ok(), "Couldn't process command");
1331         let mem_buffer = cmd_processor.current_output_memory_buffer.as_ref().unwrap();
1332         read_slice(&mem_buffer, &mut read_slice_val[..], 0).unwrap();
1333         expect_eq!(&read_slice_val[..], &[1, 2, 3, 0, 0, 0, 0, 0, 0], "initial values where not 0");
1334         cmd_list.push(CryptoOperation::CopyData(OperationData::DataBuffer(vec![4, 5, 6])));
1335         let mut cmd_processor = CmdProcessorContext::new();
1336         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1337         expect!(process_result.is_ok(), "Couldn't process command");
1338         let mem_buffer = cmd_processor.current_output_memory_buffer.as_ref().unwrap();
1339         read_slice(&mem_buffer, &mut read_slice_val[..], 0).unwrap();
1340         expect_eq!(&read_slice_val[..], &[1, 2, 3, 4, 5, 6, 0, 0, 0], "initial values where not 0");
1341         let input_reference = MemoryBufferReference { startOffset: 0, sizeBytes: 3 };
1342         cmd_list
1343             .push(CryptoOperation::CopyData(OperationData::MemoryBufferReference(input_reference)));
1344         let mut cmd_processor = CmdProcessorContext::new();
1345         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1346         expect!(process_result.is_ok(), "Couldn't process command");
1347         cmd_list.clear();
1348         let mem_buffer = cmd_processor.current_output_memory_buffer.as_ref().unwrap();
1349         read_slice(&mem_buffer, &mut read_slice_val[..], 0).unwrap();
1350         expect_eq!(&read_slice_val[..], &[1, 2, 3, 4, 5, 6, 7, 8, 9], "initial values where not 0");
1351     }
1352 
1353     #[test]
simple_copy_operation_on_initial_state()1354     fn simple_copy_operation_on_initial_state() {
1355         let mut cmd_list = Vec::<CryptoOperation>::new();
1356         let mut cmd_processor = CmdProcessorContext::new();
1357         let data_output = OperationData::DataBuffer(Vec::new());
1358         cmd_list.push(CryptoOperation::CopyData(OperationData::DataBuffer(vec![1, 2, 3])));
1359         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1360         expect!(process_result.is_err(), "Shouldn't be able to copy before adding an output");
1361         cmd_list.insert(0, CryptoOperation::DataOutput(data_output));
1362         cmd_list.push(CryptoOperation::CopyData(OperationData::DataBuffer(vec![4, 5, 6])));
1363         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1364         expect!(process_result.is_ok(), "Couldn't process commands");
1365         expect!(process_result.is_ok(), "Couldn't process second copy command");
1366         let CryptoOperation::DataOutput(OperationData::DataBuffer(output)) = &cmd_list[0] else {
1367             unreachable!("should not happen beucase we created the cmd list on the test");
1368         };
1369         expect_eq!(output, &[1, 2, 3, 4, 5, 6], "values were not copied correctly");
1370     }
1371 
1372     #[test]
simple_copy_opeartion_on_initial_state_buffer_reference_input()1373     fn simple_copy_opeartion_on_initial_state_buffer_reference_input() {
1374         let mut cmd_list = Vec::<CryptoOperation>::new();
1375         let mut cmd_processor = CmdProcessorContext::new();
1376         let data_output = OperationData::DataBuffer(Vec::new());
1377         cmd_list.push(CryptoOperation::DataOutput(data_output));
1378         let mut input_page = TestPageAllocator::new().expect("couldn't create test page");
1379         input_page.copy_values(0, &[2, 4, 8, 3, 6, 9]).unwrap();
1380         let input_memory_buffer = MemoryBufferParameter {
1381             bufferHandle: MemoryBufferAidl::Input(Some(
1382                 input_page.get_parcel_file_descriptor().expect("couldn't create fd"),
1383             )),
1384             sizeBytes: TestPageAllocator::get_allocation_size() as i32,
1385         };
1386         cmd_list.push(CryptoOperation::SetMemoryBuffer(input_memory_buffer));
1387         let input_reference = MemoryBufferReference { startOffset: 0, sizeBytes: 3 as i32 };
1388         cmd_list
1389             .push(CryptoOperation::CopyData(OperationData::MemoryBufferReference(input_reference)));
1390         let input_reference = MemoryBufferReference { startOffset: 3, sizeBytes: 3 as i32 };
1391         //cmd_list
1392         //    .push(CryptoOperation::CopyData(OperationData::MemoryBufferReference(input_reference)));
1393         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1394         expect!(process_result.is_ok(), "Couldn't process command");
1395         let CryptoOperation::DataOutput(OperationData::DataBuffer(output)) = &cmd_list[0] else {
1396             unreachable!("should not happen beucase we created the cmd list on the test");
1397         };
1398         expect_eq!(output, &[2, 4, 8], "values were not copied correctly");
1399         let mut cmd_processor = CmdProcessorContext::new();
1400         cmd_list[2] =
1401             CryptoOperation::CopyData(OperationData::MemoryBufferReference(input_reference));
1402         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1403         expect!(process_result.is_ok(), "Couldn't process second copy command");
1404         let CryptoOperation::DataOutput(OperationData::DataBuffer(output)) = &cmd_list[0] else {
1405             unreachable!("should not happen beucase we created the cmd list on the test");
1406         };
1407         expect_eq!(output, &[2, 4, 8, 3, 6, 9], "values were not copied correctly");
1408     }
1409 
1410     #[test]
aes_simple_test()1411     fn aes_simple_test() {
1412         let usage = KeyUse::ENCRYPT_DECRYPT;
1413         let key_type = KeyType::AES_256_CBC_PKCS7_PADDING;
1414         let policy = KeyPolicy {
1415             usage,
1416             keyLifetime: KeyLifetime::EPHEMERAL,
1417             keyPermissions: Vec::new(),
1418             keyType: key_type,
1419             keyManagementKey: false,
1420         };
1421         let key = OpaqueKey::generate_opaque_key(&policy, connection_info())
1422             .expect("couldn't generate key");
1423         let nonce = [0u8; 16];
1424         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1425             nonce: nonce.into(),
1426         }));
1427         let direction = SymmetricOperation::ENCRYPT;
1428         let sym_op_params =
1429             SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
1430         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1431         let mut cmd_list = Vec::<CryptoOperation>::new();
1432         let mut cmd_processor = CmdProcessorContext::new();
1433         let data_output = OperationData::DataBuffer(Vec::new());
1434         cmd_list.push(CryptoOperation::DataOutput(data_output));
1435         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1436         let input_data = OperationData::DataBuffer("string to be encrypted".as_bytes().to_vec());
1437         cmd_list.push(CryptoOperation::DataInput(input_data));
1438         cmd_list.push(CryptoOperation::Finish(None));
1439         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1440         expect!(process_result.is_ok(), "Couldn't process command");
1441         let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
1442             cmd_list.remove(0)
1443         else {
1444             panic!("not reachable, we created this object above on the test");
1445         };
1446 
1447         // Decrypting
1448         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1449             nonce: nonce.into(),
1450         }));
1451         let direction = SymmetricOperation::DECRYPT;
1452         let sym_op_params =
1453             SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
1454         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1455         let mut cmd_list = Vec::<CryptoOperation>::new();
1456         let mut cmd_processor = CmdProcessorContext::new();
1457         let data_output = OperationData::DataBuffer(Vec::new());
1458         cmd_list.push(CryptoOperation::DataOutput(data_output));
1459         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1460         cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
1461         cmd_list.push(CryptoOperation::Finish(None));
1462         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1463         expect!(process_result.is_ok(), "Couldn't process command");
1464         let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
1465             cmd_list.remove(0)
1466         else {
1467             panic!("not reachable, we created this object above on the test");
1468         };
1469         let decrypted_msg =
1470             String::from_utf8(decrypted_data).expect("couldn't decode received message");
1471         expect_eq!(decrypted_msg, "string to be encrypted", "couldn't retrieve original message");
1472     }
1473 
1474     #[test]
data_to_process_slice_based()1475     fn data_to_process_slice_based() {
1476         let mut data = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
1477 
1478         let mut slice = DataToProcess::new_from_slice(data.as_mut());
1479 
1480         let mut read_data = [0u8; 2];
1481         slice.read_into_slice(&mut read_data, None).expect("couldn't read data");
1482 
1483         expect_eq!(read_data.len(), 2, "advanced data has wrong size");
1484         expect_eq!(slice.len(), 8, "advanced data has wrong size");
1485         expect_eq!(read_data, [0, 1], "read data had wrong values");
1486 
1487         slice.append_slice(&read_data).expect("couldn't copy data");
1488         slice.start_index = 0;
1489 
1490         let mut read_data = [0u8; 10];
1491         slice.read_into_slice(&mut read_data, None).expect("couldn't read data");
1492         expect_eq!(read_data, [0, 1, 0, 1, 4, 5, 6, 7, 8, 9], "read data had wrong values");
1493     }
1494 
1495     #[test]
copy_slice()1496     fn copy_slice() {
1497         let mut output_page = TestPageAllocator::new().expect("couldn't allocate test page");
1498         let mut output_page_2 = TestPageAllocator::new().expect("couldn't allocate test page");
1499         output_page_2.copy_values(0, &[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]).unwrap();
1500 
1501         let total_buffer_size = TestPageAllocator::get_allocation_size();
1502         let mem_buffer_parameters = MemoryBufferParameter {
1503             bufferHandle: MemoryBufferAidl::Output(Some(
1504                 output_page.get_parcel_file_descriptor().expect("couldn't create fd"),
1505             )),
1506             sizeBytes: total_buffer_size as i32,
1507         };
1508         let mut memory_buffer =
1509             MemoryBuffer::new(&mem_buffer_parameters).expect("Couldn't createa memory buffer");
1510 
1511         let mem_buffer_parameters = MemoryBufferParameter {
1512             bufferHandle: MemoryBufferAidl::Output(Some(
1513                 output_page_2.get_parcel_file_descriptor().expect("couldn't create fd"),
1514             )),
1515             sizeBytes: total_buffer_size as i32,
1516         };
1517         let mut memory_buffer_2 =
1518             MemoryBuffer::new(&mem_buffer_parameters).expect("Couldn't createa memory buffer");
1519 
1520         let mut data_to_process = DataToProcess::new_from_volatile_slice(
1521             memory_buffer.get_memory_slice().expect("couldn't get memory slice"),
1522         );
1523 
1524         let mut data_to_process_2 = DataToProcess::new_from_volatile_slice(
1525             memory_buffer_2.get_memory_slice().expect("couldn't get memory slice"),
1526         );
1527 
1528         expect_eq!(
1529             data_to_process.len(),
1530             data_to_process_2.len(),
1531             "data to process len should match at this point"
1532         );
1533         let original_size = data_to_process.len();
1534 
1535         expect_eq!(
1536             data_to_process.start_index,
1537             data_to_process_2.start_index,
1538             "start index of data to process should match"
1539         );
1540         expect_eq!(data_to_process.start_index, 0, "start index of data to process should be 0");
1541 
1542         data_to_process.read_from_slice(&mut data_to_process_2, Some(3)).expect("couldn't copy");
1543         expect_eq!(
1544             data_to_process.len(),
1545             original_size - 3,
1546             "data to process len should have decreased by 3"
1547         );
1548         expect_eq!(
1549             data_to_process_2.len(),
1550             original_size - 3,
1551             "data to process len should have decreased by 3"
1552         );
1553         expect_eq!(data_to_process.start_index, 3, "start index of data to process should be 3");
1554         expect_eq!(data_to_process_2.start_index, 3, "start index of data to process should be 3");
1555 
1556         let mut read_data = [0u8; 3];
1557         data_to_process.start_index = 0;
1558         data_to_process.read_into_slice(&mut read_data, None).expect("couldn't read data");
1559         expect_eq!(read_data, [20, 21, 22], "wrong data copied");
1560 
1561         data_to_process.read_from_slice(&mut data_to_process_2, Some(0)).expect("couldn't copy");
1562         expect_eq!(
1563             data_to_process.len(),
1564             original_size - 3,
1565             "data to process len should have decreased by 3"
1566         );
1567         expect_eq!(
1568             data_to_process_2.len(),
1569             original_size - 3,
1570             "data to process len should have decreased by 3"
1571         );
1572         expect_eq!(data_to_process.start_index, 3, "start index of data to process should be 3");
1573         expect_eq!(data_to_process_2.start_index, 3, "start index of data to process should be 3");
1574 
1575         let mut read_data = [0u8; 3];
1576         data_to_process.start_index = 0;
1577         data_to_process.read_into_slice(&mut read_data, None).expect("couldn't read data");
1578         expect_eq!(read_data, [20, 21, 22], "wrong data copied");
1579 
1580         data_to_process.read_from_slice(&mut data_to_process_2, Some(4)).expect("couldn't copy");
1581         expect_eq!(
1582             data_to_process.len(),
1583             original_size - 7,
1584             "data to process len should have decreased by 4"
1585         );
1586         expect_eq!(
1587             data_to_process_2.len(),
1588             original_size - 7,
1589             "data to process len should have decreased by 4"
1590         );
1591         expect_eq!(data_to_process.start_index, 7, "start index of data to process should be 7");
1592         expect_eq!(data_to_process_2.start_index, 7, "start index of data to process should be 7");
1593 
1594         let mut read_data = [0u8; 7];
1595         data_to_process.start_index = 0;
1596         data_to_process.read_into_slice(&mut read_data, None).expect("couldn't read data");
1597         expect_eq!(read_data, [20, 21, 22, 23, 24, 25, 26], "wrong data copied");
1598 
1599         let mut data_process_vec = vec![0u8; 2];
1600         let mut data_process_slice = DataToProcess::new_from_slice(data_process_vec.as_mut_slice());
1601 
1602         expect_eq!(data_process_slice.len(), 2, "data to process len should be 2");
1603         expect_eq!(data_process_slice.start_index, 0, "start index of data to process should be 0");
1604 
1605         data_process_slice.read_from_slice(&mut data_to_process_2, Some(2)).expect("couldn't copy");
1606 
1607         expect_eq!(data_process_slice.len(), 0, "data to process len ahould be 0");
1608         expect_eq!(data_process_slice.start_index, 2, "start index of data to process should be 2");
1609         expect_eq!(
1610             data_to_process_2.len(),
1611             original_size - 9,
1612             "data to process len should have decreased by 2"
1613         );
1614         expect_eq!(data_to_process_2.start_index, 9, "start index of data to process should be 9");
1615 
1616         let mut read_data = [0u8; 2];
1617         data_process_slice.start_index = 0;
1618         data_process_slice.read_into_slice(&mut read_data, None).expect("couldn't read data");
1619         expect_eq!(read_data, [27, 28], "wrong data copied");
1620         data_process_slice.start_index = 0;
1621 
1622         data_to_process.read_from_slice(&mut data_process_slice, None).expect("couldn't copy");
1623         expect_eq!(
1624             data_to_process.len(),
1625             original_size - 9,
1626             "data to process len should have decreased by 2"
1627         );
1628         expect_eq!(data_to_process.start_index, 9, "start index of data to process should be 9");
1629 
1630         let mut read_data = [0u8; 9];
1631         data_to_process.start_index = 0;
1632         data_to_process.read_into_slice(&mut read_data, None).expect("couldn't read data");
1633         expect_eq!(read_data, [20, 21, 22, 23, 24, 25, 26, 27, 28], "wrong data copied");
1634 
1635         let mut data_process_vec_2 = vec![0u8; 9];
1636         let mut data_process_slice_2 =
1637             DataToProcess::new_from_slice(data_process_vec_2.as_mut_slice());
1638 
1639         data_process_slice.start_index = 0;
1640 
1641         data_process_slice_2.read_from_slice(&mut data_process_slice, None).expect("couldn't copy");
1642 
1643         let mut read_data = [0u8; 9];
1644         data_process_slice_2.start_index = 0;
1645         data_process_slice_2.read_into_slice(&mut read_data, None).expect("couldn't read data");
1646         expect_eq!(read_data, [27, 28, 0, 0, 0, 0, 0, 0, 0], "wrong data copied");
1647     }
1648 
1649     #[test]
data_to_process_memory_reference_copies()1650     fn data_to_process_memory_reference_copies() {
1651         let mut output_page = TestPageAllocator::new().expect("couldn't allocate test page");
1652         let mut output_page_2 = TestPageAllocator::new().expect("couldn't allocate test page");
1653         output_page_2.copy_values(0, &[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]).unwrap();
1654 
1655         let total_buffer_size = TestPageAllocator::get_allocation_size();
1656         let mem_buffer_parameters = MemoryBufferParameter {
1657             bufferHandle: MemoryBufferAidl::Output(Some(
1658                 output_page.get_parcel_file_descriptor().expect("couldn't create fd"),
1659             )),
1660             sizeBytes: total_buffer_size as i32,
1661         };
1662         let mut memory_buffer =
1663             MemoryBuffer::new(&mem_buffer_parameters).expect("Couldn't createa memory buffer");
1664 
1665         let mem_buffer_parameters = MemoryBufferParameter {
1666             bufferHandle: MemoryBufferAidl::Output(Some(
1667                 output_page_2.get_parcel_file_descriptor().expect("couldn't create fd"),
1668             )),
1669             sizeBytes: total_buffer_size as i32,
1670         };
1671         let mut memory_buffer_2 =
1672             MemoryBuffer::new(&mem_buffer_parameters).expect("Couldn't createa memory buffer");
1673 
1674         let mut data_to_process = DataToProcess::new_from_volatile_slice(
1675             memory_buffer.get_memory_slice().expect("couldn't get memory slice"),
1676         );
1677 
1678         expect_eq!(data_to_process.len(), total_buffer_size, "data to process had the wrong size");
1679 
1680         let res = data_to_process.append_slice(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
1681         expect!(res.is_ok(), "Couldn't write slice");
1682         data_to_process.start_index = 0;
1683 
1684         let mut read_data = [0u8; 2];
1685         data_to_process.read_into_slice(&mut read_data, None).expect("couldn't read data");
1686         expect_eq!(read_data, [0, 1], "wrong data read");
1687         expect_eq!(
1688             data_to_process.len(),
1689             total_buffer_size - 2,
1690             "data to process had the wrong size"
1691         );
1692 
1693         expect_eq!(data_to_process.start_index, 2, "start index should be 2");
1694 
1695         let res = data_to_process.append_slice(&[10, 11]);
1696         expect!(res.is_ok(), "Couldn't write slice");
1697 
1698         expect_eq!(data_to_process.start_index, 4, "start index should be 4");
1699 
1700         let mut data_to_process_2 = DataToProcess::new_from_volatile_slice(
1701             memory_buffer_2.get_memory_slice().expect("couldn't get memory slice"),
1702         );
1703 
1704         let mut read_data = [0u8; 7];
1705         data_to_process_2.read_into_slice(&mut read_data, None).expect("couldn't read data");
1706         expect_eq!(read_data, [20, 21, 22, 23, 24, 25, 26], "wrong data read");
1707         expect_eq!(
1708             data_to_process_2.len(),
1709             total_buffer_size - 7,
1710             "data to process had the wrong size"
1711         );
1712 
1713         expect_eq!(data_to_process_2.start_index, 7, "start index should be 7");
1714 
1715         let mut read_data = [0u8; 2];
1716         data_to_process_2.read_into_slice(&mut read_data, None).expect("couldn't read data");
1717         expect_eq!(read_data, [27, 28], "wrong data read");
1718         expect_eq!(
1719             data_to_process_2.len(),
1720             total_buffer_size - 9,
1721             "data to process had the wrong size"
1722         );
1723 
1724         let mut data_process_slice = DataToProcess::new_from_slice(&mut read_data);
1725         let res = data_to_process.read_from_slice(&mut data_process_slice, None);
1726         expect!(res.is_ok(), "Couldn't data to process");
1727 
1728         let mut slice = vec![0; 10];
1729         read_slice(&memory_buffer, &mut slice, 0).expect("couldn't get slice");
1730         expect_eq!(
1731             slice,
1732             [0, 1, 10, 11, 27, 28, 6, 7, 8, 9],
1733             "wrong value retrieved through slice"
1734         );
1735     }
1736 
1737     #[test]
aes_simple_cbcs_test()1738     fn aes_simple_cbcs_test() {
1739         let usage = KeyUse::ENCRYPT_DECRYPT;
1740         let key_type = KeyType::AES_128_CBC_NO_PADDING;
1741         let policy = KeyPolicy {
1742             usage,
1743             keyLifetime: KeyLifetime::EPHEMERAL,
1744             keyPermissions: Vec::new(),
1745             keyType: key_type,
1746             keyManagementKey: false,
1747         };
1748         let key = OpaqueKey::generate_opaque_key(&policy, connection_info())
1749             .expect("couldn't generate key");
1750         let nonce = [0u8; 16];
1751         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1752             nonce: nonce.into(),
1753         }));
1754         let direction = SymmetricOperation::ENCRYPT;
1755         let sym_op_params =
1756             SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
1757         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1758         let mut cmd_list = Vec::<CryptoOperation>::new();
1759         let mut cmd_processor = CmdProcessorContext::new();
1760         let data_output = OperationData::DataBuffer(Vec::new());
1761         cmd_list.push(CryptoOperation::DataOutput(data_output));
1762         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1763         cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
1764             numberBlocksProcess: 1,
1765             numberBlocksCopy: 9,
1766         }));
1767         let input_data =
1768             OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
1769         cmd_list.push(CryptoOperation::DataInput(input_data));
1770         let input_data =
1771             OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
1772         cmd_list.push(CryptoOperation::DataInput(input_data));
1773         let input_data =
1774             OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
1775         cmd_list.push(CryptoOperation::DataInput(input_data));
1776         let input_data =
1777             OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
1778         cmd_list.push(CryptoOperation::DataInput(input_data));
1779         let input_data = OperationData::DataBuffer(
1780             "fedcba98765432100123456789abcdefProtectedSection".as_bytes().to_vec(),
1781         );
1782         cmd_list.push(CryptoOperation::DataInput(input_data));
1783         cmd_list.push(CryptoOperation::Finish(None));
1784         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1785         expect!(process_result.is_ok(), "Couldn't process command");
1786         let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
1787             cmd_list.remove(0)
1788         else {
1789             panic!("not reachable, we created this object above on the test");
1790         };
1791         let clear_encrypted_msg =
1792             String::from_utf8(encrypted_data[16..encrypted_data.len() - 16].to_vec())
1793                 .expect("couldn't decode received message");
1794         expect_eq!(
1795             clear_encrypted_msg,
1796             "0123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210\
1797             0123456789abcdeffedcba98765432100123456789abcdeffedcba98765432100123456789abcdef",
1798             "couldn't retrieve clear portion"
1799         );
1800 
1801         // Decrypting
1802         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1803             nonce: nonce.into(),
1804         }));
1805         let direction = SymmetricOperation::DECRYPT;
1806         let sym_op_params =
1807             SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
1808         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1809         let mut cmd_list = Vec::<CryptoOperation>::new();
1810         let mut cmd_processor = CmdProcessorContext::new();
1811         let data_output = OperationData::DataBuffer(Vec::new());
1812         cmd_list.push(CryptoOperation::DataOutput(data_output));
1813         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1814         cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
1815             numberBlocksProcess: 1,
1816             numberBlocksCopy: 9,
1817         }));
1818         cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
1819         cmd_list.push(CryptoOperation::Finish(None));
1820         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1821         expect!(process_result.is_ok(), "Couldn't process command");
1822         let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
1823             cmd_list.remove(0)
1824         else {
1825             panic!("not reachable, we created this object above on the test");
1826         };
1827         let decrypted_msg =
1828             String::from_utf8(decrypted_data).expect("couldn't decode received message");
1829         expect_eq!(
1830             decrypted_msg,
1831             "encryption data.0123456789abcdeffedcba9876543210\
1832             0123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210\
1833             0123456789abcdeffedcba98765432100123456789abcdefProtectedSection",
1834             "couldn't retrieve original message"
1835         );
1836     }
1837 
1838     #[test]
check_cbcs_wrong_key_types()1839     fn check_cbcs_wrong_key_types() {
1840         let usage = KeyUse::ENCRYPT_DECRYPT;
1841         let policy = KeyPolicy {
1842             usage,
1843             keyLifetime: KeyLifetime::EPHEMERAL,
1844             keyPermissions: Vec::new(),
1845             keyType: KeyType::AES_128_CBC_PKCS7_PADDING,
1846             keyManagementKey: false,
1847         };
1848         let key = OpaqueKey::generate_opaque_key(&policy, connection_info())
1849             .expect("couldn't generate key");
1850         let nonce = [0u8; 16];
1851         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1852             nonce: nonce.into(),
1853         }));
1854         let direction = SymmetricOperation::ENCRYPT;
1855         let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
1856         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1857         let mut cmd_list = Vec::<CryptoOperation>::new();
1858         let mut cmd_processor = CmdProcessorContext::new();
1859         let data_output = OperationData::DataBuffer(Vec::new());
1860         cmd_list.push(CryptoOperation::DataOutput(data_output));
1861         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1862         cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
1863             numberBlocksProcess: 1,
1864             numberBlocksCopy: 9,
1865         }));
1866         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1867         expect!(process_result.is_err(), "Should not be able to use cbcs mode with this key type");
1868 
1869         let policy = KeyPolicy {
1870             usage,
1871             keyLifetime: KeyLifetime::EPHEMERAL,
1872             keyPermissions: Vec::new(),
1873             keyType: KeyType::AES_256_CBC_NO_PADDING,
1874             keyManagementKey: false,
1875         };
1876         let key = OpaqueKey::generate_opaque_key(&policy, connection_info())
1877             .expect("couldn't generate key");
1878         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1879             nonce: nonce.into(),
1880         }));
1881         let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
1882         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1883         let mut cmd_list = Vec::<CryptoOperation>::new();
1884         let mut cmd_processor = CmdProcessorContext::new();
1885         let data_output = OperationData::DataBuffer(Vec::new());
1886         cmd_list.push(CryptoOperation::DataOutput(data_output));
1887         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1888         cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
1889             numberBlocksProcess: 1,
1890             numberBlocksCopy: 9,
1891         }));
1892         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1893         expect!(process_result.is_err(), "Should not be able to use cbcs mode with this key type");
1894     }
1895 
1896     #[test]
aes_simple_all_encrypted_cbcs_test()1897     fn aes_simple_all_encrypted_cbcs_test() {
1898         let usage = KeyUse::ENCRYPT_DECRYPT;
1899         let key_type = KeyType::AES_128_CBC_NO_PADDING;
1900         let policy = KeyPolicy {
1901             usage,
1902             keyLifetime: KeyLifetime::EPHEMERAL,
1903             keyPermissions: Vec::new(),
1904             keyType: key_type,
1905             keyManagementKey: false,
1906         };
1907         let key = OpaqueKey::generate_opaque_key(&policy, connection_info())
1908             .expect("couldn't generate key");
1909         let nonce = [0u8; 16];
1910         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1911             nonce: nonce.into(),
1912         }));
1913         let direction = SymmetricOperation::ENCRYPT;
1914         let sym_op_params =
1915             SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
1916         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1917         let mut cmd_list = Vec::<CryptoOperation>::new();
1918         let mut cmd_processor = CmdProcessorContext::new();
1919         let data_output = OperationData::DataBuffer(Vec::new());
1920         cmd_list.push(CryptoOperation::DataOutput(data_output));
1921         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1922         cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
1923             numberBlocksProcess: 1,
1924             numberBlocksCopy: 0,
1925         }));
1926         let input_data =
1927             OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
1928         cmd_list.push(CryptoOperation::DataInput(input_data));
1929         let input_data =
1930             OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
1931         cmd_list.push(CryptoOperation::DataInput(input_data));
1932         cmd_list.push(CryptoOperation::Finish(None));
1933         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1934         expect!(process_result.is_ok(), "Couldn't process command");
1935         let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
1936             cmd_list.remove(0)
1937         else {
1938             panic!("not reachable, we created this object above on the test");
1939         };
1940 
1941         // Checking that encrypting with patter 0,0 is equivalent to pattern 1,0
1942         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1943             nonce: nonce.into(),
1944         }));
1945         let direction = SymmetricOperation::ENCRYPT;
1946         let sym_op_params =
1947             SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
1948         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1949         let mut cmd_list = Vec::<CryptoOperation>::new();
1950         let mut cmd_processor = CmdProcessorContext::new();
1951         let data_output = OperationData::DataBuffer(Vec::new());
1952         cmd_list.push(CryptoOperation::DataOutput(data_output));
1953         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1954         cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
1955             numberBlocksProcess: 0,
1956             numberBlocksCopy: 0,
1957         }));
1958         let input_data =
1959             OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
1960         cmd_list.push(CryptoOperation::DataInput(input_data));
1961         let input_data =
1962             OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
1963         cmd_list.push(CryptoOperation::DataInput(input_data));
1964         cmd_list.push(CryptoOperation::Finish(None));
1965         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1966         expect!(process_result.is_ok(), "Couldn't process command");
1967         let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data1)) =
1968             cmd_list.remove(0)
1969         else {
1970             panic!("not reachable, we created this object above on the test");
1971         };
1972         assert_eq!(encrypted_data, encrypted_data1, "encrypted data should match");
1973 
1974         // Decrypting
1975         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
1976             nonce: nonce.into(),
1977         }));
1978         let direction = SymmetricOperation::DECRYPT;
1979         let sym_op_params =
1980             SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
1981         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
1982         let mut cmd_list = Vec::<CryptoOperation>::new();
1983         let mut cmd_processor = CmdProcessorContext::new();
1984         let data_output = OperationData::DataBuffer(Vec::new());
1985         cmd_list.push(CryptoOperation::DataOutput(data_output));
1986         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
1987         cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
1988         cmd_list.push(CryptoOperation::Finish(None));
1989         let process_result = cmd_processor.process_all_steps(&mut cmd_list);
1990         expect!(process_result.is_ok(), "Couldn't process command");
1991         let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
1992             cmd_list.remove(0)
1993         else {
1994             panic!("not reachable, we created this object above on the test");
1995         };
1996         let decrypted_msg =
1997             String::from_utf8(decrypted_data).expect("couldn't decode received message");
1998         expect_eq!(
1999             decrypted_msg,
2000             "encryption data.0123456789abcdeffedcba9876543210\
2001             0123456789abcdef",
2002             "couldn't retrieve original message"
2003         );
2004     }
2005 }
2006