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}