capsules_extra/symmetric_encryption/aes.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! AES.
6
7use capsules_core::driver;
8/// Syscall driver number.
9pub const DRIVER_NUM: usize = driver::NUM::Aes as usize;
10
11use core::cell::Cell;
12
13use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
14use kernel::hil::symmetric_encryption::{
15 AES128Ctr, CCMClient, Client, GCMClient, AES128, AES128CBC, AES128CCM, AES128ECB, AES128GCM,
16 AES128_BLOCK_SIZE,
17};
18use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer};
19use kernel::syscall::{CommandReturn, SyscallDriver};
20use kernel::utilities::cells::{OptionalCell, TakeCell};
21use kernel::{ErrorCode, ProcessId};
22
23/// Ids for read-only allow buffers
24mod ro_allow {
25 pub const KEY: usize = 0;
26 pub const IV: usize = 1;
27 pub const SOURCE: usize = 2;
28 /// The number of allow buffers the kernel stores for this grant
29 pub const COUNT: u8 = 3;
30}
31
32/// Ids for read-write allow buffers
33mod rw_allow {
34 pub const DEST: usize = 0;
35 /// The number of allow buffers the kernel stores for this grant
36 pub const COUNT: u8 = 1;
37}
38
39pub struct AesDriver<'a, A: AES128<'a> + AES128CCM<'static> + AES128GCM<'static>> {
40 aes: &'a A,
41
42 active: Cell<bool>,
43
44 apps: Grant<
45 App,
46 UpcallCount<1>,
47 AllowRoCount<{ ro_allow::COUNT }>,
48 AllowRwCount<{ rw_allow::COUNT }>,
49 >,
50 processid: OptionalCell<ProcessId>,
51
52 source_buffer: TakeCell<'static, [u8]>,
53 data_copied: Cell<usize>,
54 dest_buffer: TakeCell<'static, [u8]>,
55}
56
57impl<
58 A: AES128<'static>
59 + AES128Ctr
60 + AES128CBC
61 + AES128ECB
62 + AES128CCM<'static>
63 + AES128GCM<'static>,
64 > AesDriver<'static, A>
65{
66 pub fn new(
67 aes: &'static A,
68 source_buffer: &'static mut [u8],
69 dest_buffer: &'static mut [u8],
70 grant: Grant<
71 App,
72 UpcallCount<1>,
73 AllowRoCount<{ ro_allow::COUNT }>,
74 AllowRwCount<{ rw_allow::COUNT }>,
75 >,
76 ) -> AesDriver<'static, A> {
77 AesDriver {
78 aes,
79 active: Cell::new(false),
80 apps: grant,
81 processid: OptionalCell::empty(),
82 source_buffer: TakeCell::new(source_buffer),
83 data_copied: Cell::new(0),
84 dest_buffer: TakeCell::new(dest_buffer),
85 }
86 }
87
88 fn run(&self) -> Result<(), ErrorCode> {
89 self.processid.map_or(Err(ErrorCode::RESERVE), |processid| {
90 self.apps
91 .enter(processid, |app, kernel_data| {
92 self.aes.enable();
93 match app.aes_operation {
94 Some(AesOperation::AES128Ctr(encrypt)) => {
95 self.aes.set_mode_aes128ctr(encrypt)?
96 }
97 Some(AesOperation::AES128CBC(encrypt)) => {
98 self.aes.set_mode_aes128cbc(encrypt)?
99 }
100 Some(AesOperation::AES128ECB(encrypt)) => {
101 self.aes.set_mode_aes128ecb(encrypt)?
102 }
103 Some(AesOperation::AES128CCM(_encrypt)) => {}
104 Some(AesOperation::AES128GCM(_encrypt)) => {}
105 _ => return Err(ErrorCode::INVAL),
106 }
107
108 kernel_data
109 .get_readonly_processbuffer(ro_allow::KEY)
110 .and_then(|key| {
111 key.enter(|key| {
112 let mut static_buffer_len = 0;
113 self.source_buffer.map_or(Err(ErrorCode::NOMEM), |buf| {
114 // Determine the size of the static buffer we have
115 static_buffer_len = buf.len();
116
117 if static_buffer_len > key.len() {
118 static_buffer_len = key.len()
119 }
120
121 // Copy the data into the static buffer
122 key[..static_buffer_len]
123 .copy_to_slice(&mut buf[..static_buffer_len]);
124
125 if let Some(op) = app.aes_operation.as_ref() {
126 match op {
127 AesOperation::AES128Ctr(_)
128 | AesOperation::AES128CBC(_)
129 | AesOperation::AES128ECB(_) => {
130 AES128::set_key(self.aes, buf)?;
131 Ok(())
132 }
133 AesOperation::AES128CCM(_) => {
134 AES128CCM::set_key(self.aes, buf)?;
135 Ok(())
136 }
137 AesOperation::AES128GCM(_) => {
138 AES128GCM::set_key(self.aes, buf)?;
139 Ok(())
140 }
141 }
142 } else {
143 Err(ErrorCode::FAIL)
144 }
145 })
146 })
147 })
148 .unwrap_or(Err(ErrorCode::RESERVE))?;
149
150 kernel_data
151 .get_readonly_processbuffer(ro_allow::IV)
152 .and_then(|iv| {
153 iv.enter(|iv| {
154 let mut static_buffer_len = 0;
155 self.source_buffer.map_or(Err(ErrorCode::NOMEM), |buf| {
156 // Determine the size of the static buffer we have
157 static_buffer_len = buf.len();
158
159 if static_buffer_len > iv.len() {
160 static_buffer_len = iv.len()
161 }
162
163 // Copy the data into the static buffer
164 iv[..static_buffer_len]
165 .copy_to_slice(&mut buf[..static_buffer_len]);
166
167 if let Some(op) = app.aes_operation.as_ref() {
168 match op {
169 AesOperation::AES128Ctr(_)
170 | AesOperation::AES128CBC(_)
171 | AesOperation::AES128ECB(_) => {
172 AES128::set_iv(self.aes, buf)?;
173 Ok(())
174 }
175 AesOperation::AES128CCM(_) => {
176 AES128CCM::set_nonce(self.aes, &buf[0..13])?;
177 Ok(())
178 }
179 AesOperation::AES128GCM(_) => {
180 AES128GCM::set_iv(self.aes, &buf[0..13])?;
181 Ok(())
182 }
183 }
184 } else {
185 Err(ErrorCode::FAIL)
186 }
187 })
188 })
189 })
190 .unwrap_or(Err(ErrorCode::RESERVE))?;
191
192 kernel_data
193 .get_readonly_processbuffer(ro_allow::SOURCE)
194 .and_then(|source| {
195 source.enter(|source| {
196 let mut static_buffer_len = 0;
197
198 if let Some(op) = app.aes_operation.as_ref() {
199 match op {
200 AesOperation::AES128Ctr(_)
201 | AesOperation::AES128CBC(_)
202 | AesOperation::AES128ECB(_) => {
203 self.source_buffer.map_or(
204 Err(ErrorCode::NOMEM),
205 |buf| {
206 // Determine the size of the static buffer we have
207 static_buffer_len = buf.len();
208
209 if static_buffer_len > source.len() {
210 static_buffer_len = source.len()
211 }
212
213 // Copy the data into the static buffer
214 source[..static_buffer_len].copy_to_slice(
215 &mut buf[..static_buffer_len],
216 );
217
218 self.data_copied.set(static_buffer_len);
219
220 Ok(())
221 },
222 )?;
223 }
224 AesOperation::AES128CCM(_) => {
225 self.dest_buffer.map_or(
226 Err(ErrorCode::NOMEM),
227 |buf| {
228 // Determine the size of the static buffer we have
229 static_buffer_len = buf.len();
230
231 if static_buffer_len > source.len() {
232 static_buffer_len = source.len()
233 }
234
235 // Copy the data into the static buffer
236 source[..static_buffer_len].copy_to_slice(
237 &mut buf[..static_buffer_len],
238 );
239
240 self.data_copied.set(static_buffer_len);
241
242 Ok(())
243 },
244 )?;
245 }
246 AesOperation::AES128GCM(_) => {
247 self.dest_buffer.map_or(
248 Err(ErrorCode::NOMEM),
249 |buf| {
250 // Determine the size of the static buffer we have
251 static_buffer_len = buf.len();
252
253 if static_buffer_len > source.len() {
254 static_buffer_len = source.len()
255 }
256
257 // Copy the data into the static buffer
258 source[..static_buffer_len].copy_to_slice(
259 &mut buf[..static_buffer_len],
260 );
261
262 self.data_copied.set(static_buffer_len);
263
264 Ok(())
265 },
266 )?;
267 }
268 }
269
270 self.calculate_output(
271 op,
272 app.aoff.get(),
273 app.moff.get(),
274 app.mlen.get(),
275 app.mic_len.get(),
276 app.confidential.get(),
277 )?;
278 Ok(())
279 } else {
280 Err(ErrorCode::FAIL)
281 }
282 })
283 })
284 .unwrap_or(Err(ErrorCode::RESERVE))?;
285
286 Ok(())
287 })
288 .unwrap_or_else(|err| Err(err.into()))
289 })
290 }
291
292 fn calculate_output(
293 &self,
294 op: &AesOperation,
295 aoff: usize,
296 moff: usize,
297 mlen: usize,
298 mic_len: usize,
299 confidential: bool,
300 ) -> Result<(), ErrorCode> {
301 match op {
302 AesOperation::AES128Ctr(_)
303 | AesOperation::AES128CBC(_)
304 | AesOperation::AES128ECB(_) => {
305 if let Some(dest_buf) = self.dest_buffer.take() {
306 if let Some((e, source, dest)) = AES128::crypt(
307 self.aes,
308 self.source_buffer.take(),
309 dest_buf,
310 0,
311 AES128_BLOCK_SIZE,
312 ) {
313 // Error, clear the processid and data
314 self.aes.disable();
315 self.processid.clear();
316 if let Some(source_buf) = source {
317 self.source_buffer.replace(source_buf);
318 }
319 self.dest_buffer.replace(dest);
320
321 return e;
322 }
323 } else {
324 return Err(ErrorCode::FAIL);
325 }
326 }
327 AesOperation::AES128CCM(encrypting) => {
328 if let Some(buf) = self.dest_buffer.take() {
329 if let Err((e, dest)) = AES128CCM::crypt(
330 self.aes,
331 buf,
332 aoff,
333 moff,
334 mlen,
335 mic_len,
336 confidential,
337 *encrypting,
338 ) {
339 // Error, clear the processid and data
340 self.aes.disable();
341 self.processid.clear();
342 self.dest_buffer.replace(dest);
343
344 return Err(e);
345 }
346 } else {
347 return Err(ErrorCode::FAIL);
348 }
349 }
350 AesOperation::AES128GCM(encrypting) => {
351 if let Some(buf) = self.dest_buffer.take() {
352 if let Err((e, dest)) =
353 AES128GCM::crypt(self.aes, buf, aoff, moff, mlen, *encrypting)
354 {
355 // Error, clear the appid and data
356 self.aes.disable();
357 self.processid.clear();
358 self.dest_buffer.replace(dest);
359
360 return Err(e);
361 }
362 } else {
363 return Err(ErrorCode::FAIL);
364 }
365 }
366 }
367
368 Ok(())
369 }
370
371 fn check_queue(&self) {
372 for appiter in self.apps.iter() {
373 let started_command = appiter.enter(|app, _| {
374 // If an app is already running let it complete
375 if self.processid.is_some() {
376 return true;
377 }
378
379 // If this app has a pending command let's use it.
380 app.pending_run_app.take().is_some_and(|processid| {
381 // Mark this driver as being in use.
382 self.processid.set(processid);
383 // Actually make the buzz happen.
384 self.run() == Ok(())
385 })
386 });
387 if started_command {
388 break;
389 }
390 }
391 }
392}
393
394impl<
395 A: AES128<'static>
396 + AES128Ctr
397 + AES128CBC
398 + AES128ECB
399 + AES128CCM<'static>
400 + AES128GCM<'static>,
401 > Client<'static> for AesDriver<'static, A>
402{
403 fn crypt_done(&self, source: Option<&'static mut [u8]>, destination: &'static mut [u8]) {
404 if let Some(source_buf) = source {
405 self.source_buffer.replace(source_buf);
406 }
407 self.dest_buffer.replace(destination);
408
409 self.processid.map(|id| {
410 self.apps
411 .enter(id, |app, kernel_data| {
412 let mut data_len = 0;
413 let mut exit = false;
414 let mut static_buffer_len = 0;
415
416 let source_len = kernel_data
417 .get_readonly_processbuffer(ro_allow::SOURCE)
418 .map_or(0, |source| source.len());
419
420 let subtract = self
421 .source_buffer
422 .map_or(0, |buf| core::cmp::min(buf.len(), source_len));
423
424 self.dest_buffer.map(|buf| {
425 let ret = kernel_data
426 .get_readwrite_processbuffer(rw_allow::DEST)
427 .and_then(|dest| {
428 dest.mut_enter(|dest| {
429 let offset = self.data_copied.get() - subtract;
430 let app_len = dest.len();
431 let static_len = self.source_buffer.map_or(0, |source_buf| {
432 core::cmp::min(source_buf.len(), buf.len())
433 });
434
435 if app_len < static_len {
436 if app_len - offset > 0 {
437 dest[offset..app_len]
438 .copy_from_slice(&buf[0..(app_len - offset)]);
439 }
440 } else {
441 if offset + static_len <= app_len {
442 dest[offset..(offset + static_len)]
443 .copy_from_slice(&buf[0..static_len]);
444 }
445 }
446 })
447 });
448
449 if let Err(e) = ret {
450 // No data buffer, clear the processid and data
451 self.aes.disable();
452 self.processid.clear();
453 kernel_data.schedule_upcall(0, (e as usize, 0, 0)).ok();
454 exit = true;
455 }
456 });
457
458 if exit {
459 return;
460 }
461
462 self.source_buffer.map(|buf| {
463 let ret = kernel_data
464 .get_readonly_processbuffer(ro_allow::SOURCE)
465 .and_then(|source| {
466 source.enter(|source| {
467 // Determine the size of the static buffer we have
468 static_buffer_len = buf.len();
469 // Determine how much data we have already copied
470 let copied_data = self.data_copied.get();
471
472 data_len = source.len();
473
474 if data_len > copied_data {
475 let remaining_data = &source[copied_data..];
476 let remaining_len = data_len - copied_data;
477
478 if remaining_len < static_buffer_len {
479 remaining_data.copy_to_slice(&mut buf[..remaining_len]);
480 } else {
481 remaining_data[..static_buffer_len].copy_to_slice(buf);
482 }
483 }
484 Ok(())
485 })
486 })
487 .unwrap_or(Err(ErrorCode::RESERVE));
488
489 if let Err(e) = ret {
490 // No data buffer, clear the processid and data
491 self.aes.disable();
492 self.processid.clear();
493 kernel_data.schedule_upcall(0, (e as usize, 0, 0)).ok();
494 exit = true;
495 }
496 });
497
498 if exit {
499 return;
500 }
501
502 if static_buffer_len > 0 {
503 let copied_data = self.data_copied.get();
504
505 if data_len > copied_data {
506 // Update the amount of data copied
507 self.data_copied.set(copied_data + static_buffer_len);
508
509 if let Some(op) = app.aes_operation.as_ref() {
510 if self
511 .calculate_output(
512 op,
513 app.aoff.get(),
514 app.moff.get(),
515 app.mlen.get(),
516 app.mic_len.get(),
517 app.confidential.get(),
518 )
519 .is_err()
520 {
521 // Error, clear the processid and data
522 self.aes.disable();
523 self.processid.clear();
524 self.check_queue();
525 return;
526 }
527 }
528
529 // Return as we don't want to run the digest yet
530 return;
531 }
532 }
533
534 // If we get here we have finished all the crypto operations
535 kernel_data
536 .schedule_upcall(0, (0, self.data_copied.get(), 0))
537 .ok();
538 self.data_copied.set(0);
539 })
540 .map_err(|err| {
541 if err == kernel::process::Error::NoSuchApp
542 || err == kernel::process::Error::InactiveApp
543 {
544 self.processid.clear();
545 }
546 })
547 });
548 }
549}
550
551impl<
552 A: AES128<'static>
553 + AES128Ctr
554 + AES128CBC
555 + AES128ECB
556 + AES128CCM<'static>
557 + AES128GCM<'static>,
558 > CCMClient for AesDriver<'static, A>
559{
560 fn crypt_done(&self, buf: &'static mut [u8], res: Result<(), ErrorCode>, tag_is_valid: bool) {
561 self.dest_buffer.replace(buf);
562
563 self.processid.map(|id| {
564 self.apps
565 .enter(id, |_, kernel_data| {
566 let mut exit = false;
567
568 if let Err(e) = res {
569 kernel_data.schedule_upcall(0, (e as usize, 0, 0)).ok();
570 return;
571 }
572
573 self.dest_buffer.map(|buf| {
574 let ret = kernel_data
575 .get_readwrite_processbuffer(rw_allow::DEST)
576 .and_then(|dest| {
577 dest.mut_enter(|dest| {
578 let offset = self.data_copied.get()
579 - (core::cmp::min(buf.len(), dest.len()));
580 let app_len = dest.len();
581 let static_len = buf.len();
582
583 if app_len < static_len {
584 if app_len - offset > 0 {
585 dest[offset..app_len]
586 .copy_from_slice(&buf[0..(app_len - offset)]);
587 }
588 } else {
589 if offset + static_len <= app_len {
590 dest[offset..(offset + static_len)]
591 .copy_from_slice(&buf[0..static_len]);
592 }
593 }
594 })
595 });
596
597 if let Err(e) = ret {
598 // No data buffer, clear the processid and data
599 self.aes.disable();
600 self.processid.clear();
601 kernel_data.schedule_upcall(0, (e as usize, 0, 0)).ok();
602 exit = true;
603 }
604 });
605
606 if exit {
607 return;
608 }
609
610 // AES CCM is online only we can't send any more data in, so
611 // just report what we did to the app.
612 kernel_data
613 .schedule_upcall(0, (0, self.data_copied.get(), tag_is_valid as usize))
614 .ok();
615 self.data_copied.set(0);
616 })
617 .map_err(|err| {
618 if err == kernel::process::Error::NoSuchApp
619 || err == kernel::process::Error::InactiveApp
620 {
621 self.processid.clear();
622 }
623 })
624 });
625 }
626}
627
628impl<
629 A: AES128<'static>
630 + AES128Ctr
631 + AES128CBC
632 + AES128ECB
633 + AES128CCM<'static>
634 + AES128GCM<'static>,
635 > GCMClient for AesDriver<'static, A>
636{
637 fn crypt_done(&self, buf: &'static mut [u8], res: Result<(), ErrorCode>, tag_is_valid: bool) {
638 self.dest_buffer.replace(buf);
639
640 self.processid.map(|id| {
641 self.apps
642 .enter(id, |_, kernel_data| {
643 let mut exit = false;
644
645 if let Err(e) = res {
646 kernel_data.schedule_upcall(0, (e as usize, 0, 0)).ok();
647 return;
648 }
649
650 self.dest_buffer.map(|buf| {
651 let ret = kernel_data
652 .get_readwrite_processbuffer(rw_allow::DEST)
653 .and_then(|dest| {
654 dest.mut_enter(|dest| {
655 let offset = self.data_copied.get()
656 - (core::cmp::min(buf.len(), dest.len()));
657 let app_len = dest.len();
658 let static_len = buf.len();
659
660 if app_len < static_len {
661 if app_len - offset > 0 {
662 dest[offset..app_len]
663 .copy_from_slice(&buf[0..(app_len - offset)]);
664 }
665 } else {
666 if offset + static_len <= app_len {
667 dest[offset..(offset + static_len)]
668 .copy_from_slice(&buf[0..static_len]);
669 }
670 }
671 })
672 });
673
674 if let Err(e) = ret {
675 // No data buffer, clear the appid and data
676 self.aes.disable();
677 self.processid.clear();
678 kernel_data.schedule_upcall(0, (e as usize, 0, 0)).ok();
679 exit = true;
680 }
681 });
682
683 if exit {
684 return;
685 }
686
687 // AES GCM is online only we can't send any more data in, so
688 // just report what we did to the app.
689 kernel_data
690 .schedule_upcall(0, (0, self.data_copied.get(), tag_is_valid as usize))
691 .ok();
692 self.data_copied.set(0);
693 })
694 .map_err(|err| {
695 if err == kernel::process::Error::NoSuchApp
696 || err == kernel::process::Error::InactiveApp
697 {
698 self.processid.clear();
699 }
700 })
701 });
702 }
703}
704
705impl<
706 A: AES128<'static>
707 + AES128Ctr
708 + AES128CBC
709 + AES128ECB
710 + AES128CCM<'static>
711 + AES128GCM<'static>,
712 > SyscallDriver for AesDriver<'static, A>
713{
714 fn command(
715 &self,
716 command_num: usize,
717 data1: usize,
718 data2: usize,
719 processid: ProcessId,
720 ) -> CommandReturn {
721 let match_or_empty_or_nonexistant = self.processid.map_or(true, |owning_app| {
722 // We have recorded that an app has ownership of the HMAC.
723
724 // If the HMAC is still active, then we need to wait for the operation
725 // to finish and the app, whether it exists or not (it may have crashed),
726 // still owns this capsule. If the HMAC is not active, then
727 // we need to verify that that application still exists, and remove
728 // it as owner if not.
729 if self.active.get() {
730 owning_app == processid
731 } else {
732 // Check the app still exists.
733 //
734 // If the `.enter()` succeeds, then the app is still valid, and
735 // we can check if the owning app matches the one that called
736 // the command. If the `.enter()` fails, then the owning app no
737 // longer exists and we return `true` to signify the
738 // "or_nonexistant" case.
739 self.apps
740 .enter(owning_app, |_, _| owning_app == processid)
741 .unwrap_or(true)
742 }
743 });
744
745 let app_match = self.processid.map_or(false, |owning_app| {
746 // We have recorded that an app has ownership of the HMAC.
747
748 // If the HMAC is still active, then we need to wait for the operation
749 // to finish and the app, whether it exists or not (it may have crashed),
750 // still owns this capsule. If the HMAC is not active, then
751 // we need to verify that that application still exists, and remove
752 // it as owner if not.
753 if self.active.get() {
754 owning_app == processid
755 } else {
756 // Check the app still exists.
757 //
758 // If the `.enter()` succeeds, then the app is still valid, and
759 // we can check if the owning app matches the one that called
760 // the command. If the `.enter()` fails, then the owning app no
761 // longer exists and we return `true` to signify the
762 // "or_nonexistant" case.
763 self.apps
764 .enter(owning_app, |_, _| owning_app == processid)
765 .unwrap_or(true)
766 }
767 });
768
769 // Try the commands where we want to start an operation *not* entered in
770 // an app grant first.
771 if match_or_empty_or_nonexistant && command_num == 2 {
772 self.processid.set(processid);
773 let ret = self.run();
774
775 return if let Err(e) = ret {
776 self.aes.disable();
777 self.processid.clear();
778 self.check_queue();
779 CommandReturn::failure(e)
780 } else {
781 CommandReturn::success()
782 };
783 }
784
785 let ret = self
786 .apps
787 .enter(processid, |app, kernel_data| {
788 match command_num {
789 // check if present
790 0 => CommandReturn::success(),
791
792 // set_algorithm
793 1 => match data1 {
794 0 => {
795 app.aes_operation = Some(AesOperation::AES128Ctr(data2 != 0));
796 CommandReturn::success()
797 }
798 1 => {
799 app.aes_operation = Some(AesOperation::AES128CBC(data2 != 0));
800 CommandReturn::success()
801 }
802 2 => {
803 app.aes_operation = Some(AesOperation::AES128ECB(data2 != 0));
804 CommandReturn::success()
805 }
806 3 => {
807 app.aes_operation = Some(AesOperation::AES128CCM(data2 != 0));
808 CommandReturn::success()
809 }
810 4 => {
811 app.aes_operation = Some(AesOperation::AES128GCM(data2 != 0));
812 CommandReturn::success()
813 }
814 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
815 },
816
817 // setup
818 // Copy in the key and IV and run the first encryption operation
819 // This will trigger a callback
820 2 => {
821 // Some app is using the storage, we must wait.
822 if app.pending_run_app.is_some() {
823 // No more room in the queue, nowhere to store this
824 // request.
825 CommandReturn::failure(ErrorCode::NOMEM)
826 } else {
827 // We can store this, so lets do it.
828 app.pending_run_app = Some(processid);
829 CommandReturn::success()
830 }
831 }
832
833 // crypt
834 // Generate the encrypted output
835 // Multiple calls to crypt will re-use the existing state
836 // This will trigger a callback
837 3 => {
838 if app_match {
839 if let Err(e) = kernel_data
840 .get_readonly_processbuffer(ro_allow::SOURCE)
841 .and_then(|source| {
842 source.enter(|source| {
843 let mut static_buffer_len = 0;
844 self.source_buffer.map_or(
845 Err(ErrorCode::NOMEM),
846 |buf| {
847 // Determine the size of the static buffer we have
848 static_buffer_len = buf.len();
849
850 if static_buffer_len > source.len() {
851 static_buffer_len = source.len()
852 }
853
854 // Copy the data into the static buffer
855 source[..static_buffer_len]
856 .copy_to_slice(&mut buf[..static_buffer_len]);
857
858 self.data_copied.set(static_buffer_len);
859
860 Ok(())
861 },
862 )?;
863
864 if let Some(op) = app.aes_operation.as_ref() {
865 self.calculate_output(
866 op,
867 app.aoff.get(),
868 app.moff.get(),
869 app.mlen.get(),
870 app.mic_len.get(),
871 app.confidential.get(),
872 )?;
873 Ok(())
874 } else {
875 Err(ErrorCode::FAIL)
876 }
877 })
878 })
879 .unwrap_or(Err(ErrorCode::RESERVE))
880 {
881 kernel_data
882 .schedule_upcall(
883 0,
884 (kernel::errorcode::into_statuscode(e.into()), 0, 0),
885 )
886 .ok();
887 }
888 CommandReturn::success()
889 } else {
890 // We don't queue this request, the user has to call
891 // `setup` first.
892 CommandReturn::failure(ErrorCode::OFF)
893 }
894 }
895
896 // Finish
897 // Complete the operation and reset the AES
898 // This will not trigger a callback and will not process any data from userspace
899 4 => {
900 if app_match {
901 self.aes.disable();
902 self.processid.clear();
903
904 CommandReturn::success()
905 } else {
906 // We don't queue this request, the user has to call
907 // `setup` first.
908 CommandReturn::failure(ErrorCode::OFF)
909 }
910 }
911
912 // Set aoff for CCM
913 // This will not trigger a callback and will not process any data from userspace
914 5 => {
915 app.aoff.set(data1);
916 CommandReturn::success()
917 }
918
919 // Set moff for CCM
920 // This will not trigger a callback and will not process any data from userspace
921 6 => {
922 app.moff.set(data1);
923 CommandReturn::success()
924 }
925
926 // Set mic_len for CCM
927 // This will not trigger a callback and will not process any data from userspace
928 7 => {
929 app.mic_len.set(data1);
930 CommandReturn::success()
931 }
932
933 // Set confidential boolean for CCM
934 // This will not trigger a callback and will not process any data from userspace
935 8 => {
936 app.confidential.set(data1 > 0);
937 CommandReturn::success()
938 }
939
940 // default
941 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
942 }
943 })
944 .unwrap_or_else(|err| err.into());
945
946 if command_num == 4
947 || command_num == 5
948 || command_num == 6
949 || command_num == 7
950 || command_num == 8
951 {
952 self.check_queue();
953 }
954
955 ret
956 }
957
958 fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
959 self.apps.enter(processid, |_, _| {})
960 }
961}
962
963enum AesOperation {
964 AES128Ctr(bool),
965 AES128CBC(bool),
966 AES128ECB(bool),
967 AES128CCM(bool),
968 AES128GCM(bool),
969}
970
971#[derive(Default)]
972pub struct App {
973 pending_run_app: Option<ProcessId>,
974 aes_operation: Option<AesOperation>,
975
976 aoff: Cell<usize>,
977 moff: Cell<usize>,
978 mlen: Cell<usize>,
979 mic_len: Cell<usize>,
980 confidential: Cell<bool>,
981}