[PATCH 3/7] capsules: symmetric_encryption/aes: Reduce code size

From: Alistair Francis
Date: Sat Oct 09 2021 - 07:51:08 EST


From: Alistair Francis <alistair.francis@xxxxxxx>

Signed-off-by: Alistair Francis <alistair.francis@xxxxxxx>
---
capsules/src/symmetric_encryption/aes.rs | 587 ++++++++++++-----------
1 file changed, 300 insertions(+), 287 deletions(-)

diff --git a/capsules/src/symmetric_encryption/aes.rs b/capsules/src/symmetric_encryption/aes.rs
index ed3bf74e6..1aa736ce0 100644
--- a/capsules/src/symmetric_encryption/aes.rs
+++ b/capsules/src/symmetric_encryption/aes.rs
@@ -90,21 +90,25 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
key[..static_buffer_len]
.copy_to_slice(&mut buf[..static_buffer_len]);

- match app.aes_operation.as_ref().unwrap() {
- AesOperation::AES128Ctr(_)
- | AesOperation::AES128CBC(_)
- | AesOperation::AES128ECB(_) => {
- if let Err(e) = AES128::set_key(self.aes, buf) {
- return Err(e);
+ if let Some(op) = app.aes_operation.as_ref() {
+ match op {
+ AesOperation::AES128Ctr(_)
+ | AesOperation::AES128CBC(_)
+ | AesOperation::AES128ECB(_) => {
+ if let Err(e) = AES128::set_key(self.aes, buf) {
+ return Err(e);
+ }
+ Ok(())
}
- Ok(())
- }
- AesOperation::AES128CCM(_) => {
- if let Err(e) = AES128CCM::set_key(self.aes, buf) {
- return Err(e);
+ AesOperation::AES128CCM(_) => {
+ if let Err(e) = AES128CCM::set_key(self.aes, buf) {
+ return Err(e);
+ }
+ Ok(())
}
- Ok(())
}
+ } else {
+ Err(ErrorCode::FAIL)
}
})
})
@@ -125,21 +129,25 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
iv[..static_buffer_len]
.copy_to_slice(&mut buf[..static_buffer_len]);

- match app.aes_operation.as_ref().unwrap() {
- AesOperation::AES128Ctr(_)
- | AesOperation::AES128CBC(_)
- | AesOperation::AES128ECB(_) => {
- if let Err(e) = self.aes.set_iv(buf) {
- return Err(e);
+ if let Some(op) = app.aes_operation.as_ref() {
+ match op {
+ AesOperation::AES128Ctr(_)
+ | AesOperation::AES128CBC(_)
+ | AesOperation::AES128ECB(_) => {
+ if let Err(e) = self.aes.set_iv(buf) {
+ return Err(e);
+ }
+ Ok(())
}
- Ok(())
- }
- AesOperation::AES128CCM(_) => {
- if let Err(e) = self.aes.set_nonce(&buf[0..13]) {
- return Err(e);
+ AesOperation::AES128CCM(_) => {
+ if let Err(e) = self.aes.set_nonce(&buf[0..13]) {
+ return Err(e);
+ }
+ Ok(())
}
- Ok(())
}
+ } else {
+ Err(ErrorCode::FAIL)
}
})
})
@@ -149,58 +157,65 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
.enter(|source| {
let mut static_buffer_len = 0;

- match app.aes_operation.as_ref().unwrap() {
- AesOperation::AES128Ctr(_)
- | AesOperation::AES128CBC(_)
- | AesOperation::AES128ECB(_) => {
- self.source_buffer.map_or(Err(ErrorCode::NOMEM), |buf| {
- // Determine the size of the static buffer we have
- static_buffer_len = buf.len();
+ if let Some(op) = app.aes_operation.as_ref() {
+ match op {
+ AesOperation::AES128Ctr(_)
+ | AesOperation::AES128CBC(_)
+ | AesOperation::AES128ECB(_) => {
+ self.source_buffer.map_or(
+ Err(ErrorCode::NOMEM),
+ |buf| {
+ // Determine the size of the static buffer we have
+ static_buffer_len = buf.len();

- if static_buffer_len > source.len() {
- static_buffer_len = source.len()
- }
+ if static_buffer_len > source.len() {
+ static_buffer_len = source.len()
+ }

- // Copy the data into the static buffer
- source[..static_buffer_len]
- .copy_to_slice(&mut buf[..static_buffer_len]);
+ // Copy the data into the static buffer
+ source[..static_buffer_len]
+ .copy_to_slice(&mut buf[..static_buffer_len]);

- self.data_copied.set(static_buffer_len);
+ self.data_copied.set(static_buffer_len);

- Ok(())
- })?;
- }
- AesOperation::AES128CCM(_) => {
- self.dest_buffer.map_or(Err(ErrorCode::NOMEM), |buf| {
- // Determine the size of the static buffer we have
- static_buffer_len = buf.len();
+ Ok(())
+ },
+ )?;
+ }
+ AesOperation::AES128CCM(_) => {
+ self.dest_buffer.map_or(Err(ErrorCode::NOMEM), |buf| {
+ // Determine the size of the static buffer we have
+ static_buffer_len = buf.len();

- if static_buffer_len > source.len() {
- static_buffer_len = source.len()
- }
+ if static_buffer_len > source.len() {
+ static_buffer_len = source.len()
+ }

- // Copy the data into the static buffer
- source[..static_buffer_len]
- .copy_to_slice(&mut buf[..static_buffer_len]);
+ // Copy the data into the static buffer
+ source[..static_buffer_len]
+ .copy_to_slice(&mut buf[..static_buffer_len]);

- self.data_copied.set(static_buffer_len);
+ self.data_copied.set(static_buffer_len);

- Ok(())
- })?;
+ Ok(())
+ })?;
+ }
}
- }

- if let Err(e) = self.calculate_output(
- app.aes_operation.as_ref().unwrap(),
- app.aoff.get(),
- app.moff.get(),
- app.mlen.get(),
- app.mic_len.get(),
- app.confidential.get(),
- ) {
- return Err(e);
+ if let Err(e) = self.calculate_output(
+ op,
+ app.aoff.get(),
+ app.moff.get(),
+ app.mlen.get(),
+ app.mic_len.get(),
+ app.confidential.get(),
+ ) {
+ return Err(e);
+ }
+ Ok(())
+ } else {
+ Err(ErrorCode::FAIL)
}
- Ok(())
})
.unwrap_or(Err(ErrorCode::RESERVE))?;

@@ -223,40 +238,49 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
AesOperation::AES128Ctr(_)
| AesOperation::AES128CBC(_)
| AesOperation::AES128ECB(_) => {
- if let Some((e, source, dest)) = AES128::crypt(
- self.aes,
- Some(self.source_buffer.take().unwrap()),
- self.dest_buffer.take().unwrap(),
- 0,
- AES128_BLOCK_SIZE,
- ) {
- // Error, clear the appid and data
- self.aes.disable();
- self.appid.clear();
- self.source_buffer.replace(source.unwrap());
- self.dest_buffer.replace(dest);
+ if let Some(dest_buf) = self.dest_buffer.take() {
+ if let Some((e, source, dest)) = AES128::crypt(
+ self.aes,
+ self.source_buffer.take(),
+ dest_buf,
+ 0,
+ AES128_BLOCK_SIZE,
+ ) {
+ // Error, clear the appid and data
+ self.aes.disable();
+ self.appid.clear();
+ if let Some(source_buf) = source {
+ self.source_buffer.replace(source_buf);
+ }
+ self.dest_buffer.replace(dest);

- return e;
+ return e;
+ }
+ } else {
+ return Err(ErrorCode::FAIL);
}
}
AesOperation::AES128CCM(encrypting) => {
- let buf = self.dest_buffer.take().unwrap();
- if let Err((e, dest)) = AES128CCM::crypt(
- self.aes,
- buf,
- aoff,
- moff,
- mlen,
- mic_len,
- confidential,
- *encrypting,
- ) {
- // Error, clear the appid and data
- self.aes.disable();
- self.appid.clear();
- self.dest_buffer.replace(dest);
+ if let Some(buf) = self.dest_buffer.take() {
+ if let Err((e, dest)) = AES128CCM::crypt(
+ self.aes,
+ buf,
+ aoff,
+ moff,
+ mlen,
+ mic_len,
+ confidential,
+ *encrypting,
+ ) {
+ // Error, clear the appid and data
+ self.aes.disable();
+ self.appid.clear();
+ self.dest_buffer.replace(dest);

- return Err(e);
+ return Err(e);
+ }
+ } else {
+ return Err(ErrorCode::FAIL);
}
}
}
@@ -291,7 +315,9 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
Client<'static> for AesDriver<'static, A>
{
fn crypt_done(&'a self, source: Option<&'static mut [u8]>, destination: &'static mut [u8]) {
- self.source_buffer.replace(source.unwrap());
+ if let Some(source_buf) = source {
+ self.source_buffer.replace(source_buf);
+ }
self.dest_buffer.replace(destination);

self.appid.map(|id| {
@@ -384,22 +410,24 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
// Update the amount of data copied
self.data_copied.set(copied_data + static_buffer_len);

- if self
- .calculate_output(
- app.aes_operation.as_ref().unwrap(),
- app.aoff.get(),
- app.moff.get(),
- app.mlen.get(),
- app.mic_len.get(),
- app.confidential.get(),
- )
- .is_err()
- {
- // Error, clear the appid and data
- self.aes.disable();
- self.appid.clear();
- self.check_queue();
- return;
+ if let Some(op) = app.aes_operation.as_ref() {
+ if self
+ .calculate_output(
+ op,
+ app.aoff.get(),
+ app.moff.get(),
+ app.mlen.get(),
+ app.mic_len.get(),
+ app.confidential.get(),
+ )
+ .is_err()
+ {
+ // Error, clear the appid and data
+ self.aes.disable();
+ self.appid.clear();
+ self.check_queue();
+ return;
+ }
}

// Return as we don't want to run the digest yet
@@ -526,40 +554,35 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
allow_num: usize,
mut slice: ReadOnlyProcessBuffer,
) -> Result<ReadOnlyProcessBuffer, (ReadOnlyProcessBuffer, ErrorCode)> {
- let res = match allow_num {
- // Pass buffer for the key to be in
- 0 => self
- .apps
- .enter(appid, |app, _| {
- mem::swap(&mut app.key, &mut slice);
- Ok(())
- })
- .unwrap_or(Err(ErrorCode::FAIL)),
-
- // Pass buffer for the IV to be in
- // This also contains the nonce when doing AES CCM
- 1 => self
- .apps
- .enter(appid, |app, _| {
- mem::swap(&mut app.iv, &mut slice);
- Ok(())
- })
- .unwrap_or(Err(ErrorCode::FAIL)),
+ let res = self
+ .apps
+ .enter(appid, |app, _| {
+ match allow_num {
+ // Pass buffer for the key to be in
+ 0 => {
+ mem::swap(&mut app.key, &mut slice);
+ Ok(())
+ }

- // Pass buffer for the source to be in
- // If doing a CCM operation also set the mlen
- 2 => self
- .apps
- .enter(appid, |app, _| {
- mem::swap(&mut app.source, &mut slice);
- app.mlen.set(app.source.len());
- Ok(())
- })
- .unwrap_or(Err(ErrorCode::FAIL)),
+ // Pass buffer for the IV to be in
+ // This also contains the nonce when doing AES CCM
+ 1 => {
+ mem::swap(&mut app.iv, &mut slice);
+ Ok(())
+ }
+ // Pass buffer for the source to be in
+ // If doing a CCM operation also set the mlen
+ 2 => {
+ mem::swap(&mut app.source, &mut slice);
+ app.mlen.set(app.source.len());
+ Ok(())
+ }

- // default
- _ => Err(ErrorCode::NOSUPPORT),
- };
+ // default
+ _ => Err(ErrorCode::NOSUPPORT),
+ }
+ })
+ .unwrap_or(Err(ErrorCode::FAIL));

match res {
Ok(()) => Ok(slice),
@@ -622,77 +645,76 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
}
});

- match command_num {
- // check if present
- 0 => CommandReturn::success(),
+ // Try the commands where we want to start an operation *not* entered in
+ // an app grant first.
+ if match_or_empty_or_nonexistant
+ && (command_num == 2 || command_num == 2 || command_num == 4)
+ {
+ if command_num == 2 {
+ self.appid.set(appid);
+ let ret = self.run();

- // set_algorithm
- 1 => self
- .apps
- .enter(appid, |app, _| match data1 {
- 0 => {
- app.aes_operation = Some(AesOperation::AES128Ctr(data2 != 0));
- CommandReturn::success()
- }
- 1 => {
- app.aes_operation = Some(AesOperation::AES128CBC(data2 != 0));
- CommandReturn::success()
- }
- 2 => {
- app.aes_operation = Some(AesOperation::AES128ECB(data2 != 0));
- CommandReturn::success()
- }
- 3 => {
- app.aes_operation = Some(AesOperation::AES128CCM(data2 != 0));
- CommandReturn::success()
- }
- _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
- })
- .unwrap_or_else(|err| err.into()),
+ return if let Err(e) = ret {
+ self.aes.disable();
+ self.appid.clear();
+ self.check_queue();
+ CommandReturn::failure(e)
+ } else {
+ CommandReturn::success()
+ };
+ }
+ }

- // setup
- // Copy in the key and IV and run the first encryption operation
- // This will trigger a callback
- 2 => {
- if match_or_empty_or_nonexistant {
- self.appid.set(appid);
- let ret = self.run();
+ let ret = self
+ .apps
+ .enter(appid, |app, upcalls| {
+ match command_num {
+ // check if present
+ 0 => CommandReturn::success(),
+
+ // set_algorithm
+ 1 => match data1 {
+ 0 => {
+ app.aes_operation = Some(AesOperation::AES128Ctr(data2 != 0));
+ CommandReturn::success()
+ }
+ 1 => {
+ app.aes_operation = Some(AesOperation::AES128CBC(data2 != 0));
+ CommandReturn::success()
+ }
+ 2 => {
+ app.aes_operation = Some(AesOperation::AES128ECB(data2 != 0));
+ CommandReturn::success()
+ }
+ 3 => {
+ app.aes_operation = Some(AesOperation::AES128CCM(data2 != 0));
+ CommandReturn::success()
+ }
+ _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
+ },

- if let Err(e) = ret {
- self.aes.disable();
- self.appid.clear();
- self.check_queue();
- CommandReturn::failure(e)
- } else {
- CommandReturn::success()
+ // setup
+ // Copy in the key and IV and run the first encryption operation
+ // This will trigger a callback
+ 2 => {
+ // Some app is using the storage, we must wait.
+ if app.pending_run_app.is_some() {
+ // No more room in the queue, nowhere to store this
+ // request.
+ CommandReturn::failure(ErrorCode::NOMEM)
+ } else {
+ // We can store this, so lets do it.
+ app.pending_run_app = Some(appid);
+ CommandReturn::success()
+ }
}
- } else {
- // There is an active app, so queue this request (if possible).
- self.apps
- .enter(appid, |app, _| {
- // Some app is using the storage, we must wait.
- if app.pending_run_app.is_some() {
- // No more room in the queue, nowhere to store this
- // request.
- CommandReturn::failure(ErrorCode::NOMEM)
- } else {
- // We can store this, so lets do it.
- app.pending_run_app = Some(appid);
- CommandReturn::success()
- }
- })
- .unwrap_or_else(|err| err.into())
- }
- }

- // crypt
- // Generate the encrypted output
- // Multiple calls to crypt will re-use the existing state
- // This will trigger a callback
- 3 => {
- if app_match {
- self.apps
- .enter(appid, |app, upcalls| {
+ // crypt
+ // Generate the encrypted output
+ // Multiple calls to crypt will re-use the existing state
+ // This will trigger a callback
+ 3 => {
+ if app_match {
if let Err(e) = app
.source
.enter(|source| {
@@ -714,17 +736,21 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
Ok(())
})?;

- if let Err(e) = self.calculate_output(
- app.aes_operation.as_ref().unwrap(),
- app.aoff.get(),
- app.moff.get(),
- app.mlen.get(),
- app.mic_len.get(),
- app.confidential.get(),
- ) {
- return Err(e);
+ if let Some(op) = app.aes_operation.as_ref() {
+ if let Err(e) = self.calculate_output(
+ op,
+ app.aoff.get(),
+ app.moff.get(),
+ app.mlen.get(),
+ app.mic_len.get(),
+ app.confidential.get(),
+ ) {
+ return Err(e);
+ }
+ Ok(())
+ } else {
+ Err(ErrorCode::FAIL)
}
- Ok(())
})
.unwrap_or(Err(ErrorCode::RESERVE))
{
@@ -735,87 +761,74 @@ impl<'a, A: AES128<'static> + AES128Ctr + AES128CBC + AES128ECB + AES128CCM<'sta
)
.ok();
}
- })
- .unwrap();
- CommandReturn::success()
- } else {
- // We don't queue this request, the user has to call
- // `setup` first.
- CommandReturn::failure(ErrorCode::OFF)
- }
- }
+ CommandReturn::success()
+ } else {
+ // We don't queue this request, the user has to call
+ // `setup` first.
+ CommandReturn::failure(ErrorCode::OFF)
+ }
+ }

- // Finish
- // Complete the operation and reset the AES
- // This will not trigger a callback and will not process any data from userspace
- 4 => {
- if app_match {
- self.apps
- .enter(appid, |_app, _upcalls| {
+ // Finish
+ // Complete the operation and reset the AES
+ // This will not trigger a callback and will not process any data from userspace
+ 4 => {
+ if app_match {
self.aes.disable();
self.appid.clear();
- })
- .unwrap();
- self.check_queue();
- CommandReturn::success()
- } else {
- // We don't queue this request, the user has to call
- // `setup` first.
- CommandReturn::failure(ErrorCode::OFF)
- }
- }

- // Set aoff for CCM
- // This will not trigger a callback and will not process any data from userspace
- 5 => {
- self.apps
- .enter(appid, |app, _upcalls| {
+ CommandReturn::success()
+ } else {
+ // We don't queue this request, the user has to call
+ // `setup` first.
+ CommandReturn::failure(ErrorCode::OFF)
+ }
+ }
+
+ // Set aoff for CCM
+ // This will not trigger a callback and will not process any data from userspace
+ 5 => {
app.aoff.set(data1);
- })
- .unwrap();
- self.check_queue();
- CommandReturn::success()
- }
+ CommandReturn::success()
+ }

- // Set moff for CCM
- // This will not trigger a callback and will not process any data from userspace
- 6 => {
- self.apps
- .enter(appid, |app, _upcalls| {
+ // Set moff for CCM
+ // This will not trigger a callback and will not process any data from userspace
+ 6 => {
app.moff.set(data1);
- })
- .unwrap();
- self.check_queue();
- CommandReturn::success()
- }
+ CommandReturn::success()
+ }

- // Set mic_len for CCM
- // This will not trigger a callback and will not process any data from userspace
- 7 => {
- self.apps
- .enter(appid, |app, _upcalls| {
+ // Set mic_len for CCM
+ // This will not trigger a callback and will not process any data from userspace
+ 7 => {
app.mic_len.set(data1);
- })
- .unwrap();
- self.check_queue();
- CommandReturn::success()
- }
+ CommandReturn::success()
+ }

- // Set confidential boolean for CCM
- // This will not trigger a callback and will not process any data from userspace
- 8 => {
- self.apps
- .enter(appid, |app, _upcalls| {
+ // Set confidential boolean for CCM
+ // This will not trigger a callback and will not process any data from userspace
+ 8 => {
app.confidential.set(data1 > 0);
- })
- .unwrap();
- self.check_queue();
- CommandReturn::success()
- }
+ CommandReturn::success()
+ }

- // default
- _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
+ // default
+ _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
+ }
+ })
+ .unwrap_or_else(|err| err.into());
+
+ if command_num == 4
+ || command_num == 5
+ || command_num == 6
+ || command_num == 7
+ || command_num == 8
+ {
+ self.check_queue();
}
+
+ ret
}

fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
--
2.31.1