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 ¶meters.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