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                            let _ = kernel_data.schedule_upcall(0, (e as usize, 0, 0));
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                            let _ = kernel_data.schedule_upcall(0, (e as usize, 0, 0));
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                    let _ = kernel_data.schedule_upcall(0, (0, self.data_copied.get(), 0));
536                    self.data_copied.set(0);
537                })
538                .map_err(|err| {
539                    if err == kernel::process::Error::NoSuchApp
540                        || err == kernel::process::Error::InactiveApp
541                    {
542                        self.processid.clear();
543                    }
544                })
545        });
546    }
547}
548
549impl<
550        A: AES128<'static>
551            + AES128Ctr
552            + AES128CBC
553            + AES128ECB
554            + AES128CCM<'static>
555            + AES128GCM<'static>,
556    > CCMClient for AesDriver<'static, A>
557{
558    fn crypt_done(&self, buf: &'static mut [u8], res: Result<(), ErrorCode>, tag_is_valid: bool) {
559        self.dest_buffer.replace(buf);
560
561        self.processid.map(|id| {
562            self.apps
563                .enter(id, |_, kernel_data| {
564                    let mut exit = false;
565
566                    if let Err(e) = res {
567                        let _ = kernel_data.schedule_upcall(0, (e as usize, 0, 0));
568                        return;
569                    }
570
571                    self.dest_buffer.map(|buf| {
572                        let ret = kernel_data
573                            .get_readwrite_processbuffer(rw_allow::DEST)
574                            .and_then(|dest| {
575                                dest.mut_enter(|dest| {
576                                    let offset = self.data_copied.get()
577                                        - (core::cmp::min(buf.len(), dest.len()));
578                                    let app_len = dest.len();
579                                    let static_len = buf.len();
580
581                                    if app_len < static_len {
582                                        if app_len - offset > 0 {
583                                            dest[offset..app_len]
584                                                .copy_from_slice(&buf[0..(app_len - offset)]);
585                                        }
586                                    } else {
587                                        if offset + static_len <= app_len {
588                                            dest[offset..(offset + static_len)]
589                                                .copy_from_slice(&buf[0..static_len]);
590                                        }
591                                    }
592                                })
593                            });
594
595                        if let Err(e) = ret {
596                            // No data buffer, clear the processid and data
597                            self.aes.disable();
598                            self.processid.clear();
599                            let _ = kernel_data.schedule_upcall(0, (e as usize, 0, 0));
600                            exit = true;
601                        }
602                    });
603
604                    if exit {
605                        return;
606                    }
607
608                    // AES CCM is online only we can't send any more data in, so
609                    // just report what we did to the app.
610                    let _ = kernel_data
611                        .schedule_upcall(0, (0, self.data_copied.get(), tag_is_valid as usize));
612                    self.data_copied.set(0);
613                })
614                .map_err(|err| {
615                    if err == kernel::process::Error::NoSuchApp
616                        || err == kernel::process::Error::InactiveApp
617                    {
618                        self.processid.clear();
619                    }
620                })
621        });
622    }
623}
624
625impl<
626        A: AES128<'static>
627            + AES128Ctr
628            + AES128CBC
629            + AES128ECB
630            + AES128CCM<'static>
631            + AES128GCM<'static>,
632    > GCMClient for AesDriver<'static, A>
633{
634    fn crypt_done(&self, buf: &'static mut [u8], res: Result<(), ErrorCode>, tag_is_valid: bool) {
635        self.dest_buffer.replace(buf);
636
637        self.processid.map(|id| {
638            self.apps
639                .enter(id, |_, kernel_data| {
640                    let mut exit = false;
641
642                    if let Err(e) = res {
643                        let _ = kernel_data.schedule_upcall(0, (e as usize, 0, 0));
644                        return;
645                    }
646
647                    self.dest_buffer.map(|buf| {
648                        let ret = kernel_data
649                            .get_readwrite_processbuffer(rw_allow::DEST)
650                            .and_then(|dest| {
651                                dest.mut_enter(|dest| {
652                                    let offset = self.data_copied.get()
653                                        - (core::cmp::min(buf.len(), dest.len()));
654                                    let app_len = dest.len();
655                                    let static_len = buf.len();
656
657                                    if app_len < static_len {
658                                        if app_len - offset > 0 {
659                                            dest[offset..app_len]
660                                                .copy_from_slice(&buf[0..(app_len - offset)]);
661                                        }
662                                    } else {
663                                        if offset + static_len <= app_len {
664                                            dest[offset..(offset + static_len)]
665                                                .copy_from_slice(&buf[0..static_len]);
666                                        }
667                                    }
668                                })
669                            });
670
671                        if let Err(e) = ret {
672                            // No data buffer, clear the appid and data
673                            self.aes.disable();
674                            self.processid.clear();
675                            let _ = kernel_data.schedule_upcall(0, (e as usize, 0, 0));
676                            exit = true;
677                        }
678                    });
679
680                    if exit {
681                        return;
682                    }
683
684                    // AES GCM is online only we can't send any more data in, so
685                    // just report what we did to the app.
686                    let _ = kernel_data
687                        .schedule_upcall(0, (0, self.data_copied.get(), tag_is_valid as usize));
688                    self.data_copied.set(0);
689                })
690                .map_err(|err| {
691                    if err == kernel::process::Error::NoSuchApp
692                        || err == kernel::process::Error::InactiveApp
693                    {
694                        self.processid.clear();
695                    }
696                })
697        });
698    }
699}
700
701impl<
702        A: AES128<'static>
703            + AES128Ctr
704            + AES128CBC
705            + AES128ECB
706            + AES128CCM<'static>
707            + AES128GCM<'static>,
708    > SyscallDriver for AesDriver<'static, A>
709{
710    fn command(
711        &self,
712        command_num: usize,
713        data1: usize,
714        data2: usize,
715        processid: ProcessId,
716    ) -> CommandReturn {
717        let match_or_empty_or_nonexistant = self.processid.map_or(true, |owning_app| {
718            // We have recorded that an app has ownership of the HMAC.
719
720            // If the HMAC is still active, then we need to wait for the operation
721            // to finish and the app, whether it exists or not (it may have crashed),
722            // still owns this capsule. If the HMAC is not active, then
723            // we need to verify that that application still exists, and remove
724            // it as owner if not.
725            if self.active.get() {
726                owning_app == processid
727            } else {
728                // Check the app still exists.
729                //
730                // If the `.enter()` succeeds, then the app is still valid, and
731                // we can check if the owning app matches the one that called
732                // the command. If the `.enter()` fails, then the owning app no
733                // longer exists and we return `true` to signify the
734                // "or_nonexistant" case.
735                self.apps
736                    .enter(owning_app, |_, _| owning_app == processid)
737                    .unwrap_or(true)
738            }
739        });
740
741        let app_match = self.processid.map_or(false, |owning_app| {
742            // We have recorded that an app has ownership of the HMAC.
743
744            // If the HMAC is still active, then we need to wait for the operation
745            // to finish and the app, whether it exists or not (it may have crashed),
746            // still owns this capsule. If the HMAC is not active, then
747            // we need to verify that that application still exists, and remove
748            // it as owner if not.
749            if self.active.get() {
750                owning_app == processid
751            } else {
752                // Check the app still exists.
753                //
754                // If the `.enter()` succeeds, then the app is still valid, and
755                // we can check if the owning app matches the one that called
756                // the command. If the `.enter()` fails, then the owning app no
757                // longer exists and we return `true` to signify the
758                // "or_nonexistant" case.
759                self.apps
760                    .enter(owning_app, |_, _| owning_app == processid)
761                    .unwrap_or(true)
762            }
763        });
764
765        // Try the commands where we want to start an operation *not* entered in
766        // an app grant first.
767        if match_or_empty_or_nonexistant && command_num == 2 {
768            self.processid.set(processid);
769            let ret = self.run();
770
771            return if let Err(e) = ret {
772                self.aes.disable();
773                self.processid.clear();
774                self.check_queue();
775                CommandReturn::failure(e)
776            } else {
777                CommandReturn::success()
778            };
779        }
780
781        let ret = self
782            .apps
783            .enter(processid, |app, kernel_data| {
784                match command_num {
785                    // check if present
786                    0 => CommandReturn::success(),
787
788                    // set_algorithm
789                    1 => match data1 {
790                        0 => {
791                            app.aes_operation = Some(AesOperation::AES128Ctr(data2 != 0));
792                            CommandReturn::success()
793                        }
794                        1 => {
795                            app.aes_operation = Some(AesOperation::AES128CBC(data2 != 0));
796                            CommandReturn::success()
797                        }
798                        2 => {
799                            app.aes_operation = Some(AesOperation::AES128ECB(data2 != 0));
800                            CommandReturn::success()
801                        }
802                        3 => {
803                            app.aes_operation = Some(AesOperation::AES128CCM(data2 != 0));
804                            CommandReturn::success()
805                        }
806                        4 => {
807                            app.aes_operation = Some(AesOperation::AES128GCM(data2 != 0));
808                            CommandReturn::success()
809                        }
810                        _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
811                    },
812
813                    // setup
814                    // Copy in the key and IV and run the first encryption operation
815                    // This will trigger a callback
816                    2 => {
817                        // Some app is using the storage, we must wait.
818                        if app.pending_run_app.is_some() {
819                            // No more room in the queue, nowhere to store this
820                            // request.
821                            CommandReturn::failure(ErrorCode::NOMEM)
822                        } else {
823                            // We can store this, so lets do it.
824                            app.pending_run_app = Some(processid);
825                            CommandReturn::success()
826                        }
827                    }
828
829                    // crypt
830                    // Generate the encrypted output
831                    // Multiple calls to crypt will re-use the existing state
832                    // This will trigger a callback
833                    3 => {
834                        if app_match {
835                            if let Err(e) = kernel_data
836                                .get_readonly_processbuffer(ro_allow::SOURCE)
837                                .and_then(|source| {
838                                    source.enter(|source| {
839                                        let mut static_buffer_len = 0;
840                                        self.source_buffer.map_or(
841                                            Err(ErrorCode::NOMEM),
842                                            |buf| {
843                                                // Determine the size of the static buffer we have
844                                                static_buffer_len = buf.len();
845
846                                                if static_buffer_len > source.len() {
847                                                    static_buffer_len = source.len()
848                                                }
849
850                                                // Copy the data into the static buffer
851                                                source[..static_buffer_len]
852                                                    .copy_to_slice(&mut buf[..static_buffer_len]);
853
854                                                self.data_copied.set(static_buffer_len);
855
856                                                Ok(())
857                                            },
858                                        )?;
859
860                                        if let Some(op) = app.aes_operation.as_ref() {
861                                            self.calculate_output(
862                                                op,
863                                                app.aoff.get(),
864                                                app.moff.get(),
865                                                app.mlen.get(),
866                                                app.mic_len.get(),
867                                                app.confidential.get(),
868                                            )?;
869                                            Ok(())
870                                        } else {
871                                            Err(ErrorCode::FAIL)
872                                        }
873                                    })
874                                })
875                                .unwrap_or(Err(ErrorCode::RESERVE))
876                            {
877                                let _ = kernel_data.schedule_upcall(
878                                    0,
879                                    (kernel::errorcode::into_statuscode(e.into()), 0, 0),
880                                );
881                            }
882                            CommandReturn::success()
883                        } else {
884                            // We don't queue this request, the user has to call
885                            // `setup` first.
886                            CommandReturn::failure(ErrorCode::OFF)
887                        }
888                    }
889
890                    // Finish
891                    // Complete the operation and reset the AES
892                    // This will not trigger a callback and will not process any data from userspace
893                    4 => {
894                        if app_match {
895                            self.aes.disable();
896                            self.processid.clear();
897
898                            CommandReturn::success()
899                        } else {
900                            // We don't queue this request, the user has to call
901                            // `setup` first.
902                            CommandReturn::failure(ErrorCode::OFF)
903                        }
904                    }
905
906                    // Set aoff for CCM
907                    // This will not trigger a callback and will not process any data from userspace
908                    5 => {
909                        app.aoff.set(data1);
910                        CommandReturn::success()
911                    }
912
913                    // Set moff for CCM
914                    // This will not trigger a callback and will not process any data from userspace
915                    6 => {
916                        app.moff.set(data1);
917                        CommandReturn::success()
918                    }
919
920                    // Set mic_len for CCM
921                    // This will not trigger a callback and will not process any data from userspace
922                    7 => {
923                        app.mic_len.set(data1);
924                        CommandReturn::success()
925                    }
926
927                    // Set confidential boolean for CCM
928                    // This will not trigger a callback and will not process any data from userspace
929                    8 => {
930                        app.confidential.set(data1 > 0);
931                        CommandReturn::success()
932                    }
933
934                    // default
935                    _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
936                }
937            })
938            .unwrap_or_else(|err| err.into());
939
940        if command_num == 4
941            || command_num == 5
942            || command_num == 6
943            || command_num == 7
944            || command_num == 8
945        {
946            self.check_queue();
947        }
948
949        ret
950    }
951
952    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
953        self.apps.enter(processid, |_, _| {})
954    }
955}
956
957enum AesOperation {
958    AES128Ctr(bool),
959    AES128CBC(bool),
960    AES128ECB(bool),
961    AES128CCM(bool),
962    AES128GCM(bool),
963}
964
965#[derive(Default)]
966pub struct App {
967    pending_run_app: Option<ProcessId>,
968    aes_operation: Option<AesOperation>,
969
970    aoff: Cell<usize>,
971    moff: Cell<usize>,
972    mlen: Cell<usize>,
973    mic_len: Cell<usize>,
974    confidential: Cell<bool>,
975}