sam4l/
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//! Implementation of the AESA peripheral on the SAM4L.
6//!
7//! Authors:
8//!
9//! - Daniel Giffin  <daniel@beech-grove.net>
10//! - Hubert Teo <hubert.teo.hk@gmail.com>
11//! - Brad Campbell <bradjc5@gmail.com>
12//!
13//! Converted to new register abstraction by Philip Levis <pal@cs.stanford.edu>
14
15use crate::pm;
16use crate::scif;
17use core::cell::Cell;
18use kernel::debug;
19use kernel::hil;
20use kernel::hil::symmetric_encryption::{AES128_BLOCK_SIZE, AES128_KEY_SIZE};
21use kernel::utilities::cells::{OptionalCell, TakeCell};
22use kernel::utilities::registers::interfaces::{Readable, Writeable};
23use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
24use kernel::utilities::StaticRef;
25use kernel::ErrorCode;
26
27#[allow(dead_code)]
28#[derive(Copy, Clone)]
29enum ConfidentialityMode {
30    ECB = 0,
31    CBC = 1,
32    CFB = 2,
33    OFB = 3,
34    CTR = 4,
35}
36
37/// The registers used to interface with the hardware
38#[repr(C)]
39struct AesRegisters {
40    ctrl: ReadWrite<u32, Control::Register>,         //   0x00
41    mode: ReadWrite<u32, Mode::Register>,            //   0x04
42    databufptr: ReadWrite<u32, DataBuf::Register>,   //   0x08
43    sr: ReadOnly<u32, Status::Register>,             //   0x0c
44    ier: WriteOnly<u32, Interrupt::Register>,        //   0x10
45    idr: WriteOnly<u32, Interrupt::Register>,        //   0x14
46    imr: ReadOnly<u32, Interrupt::Register>,         //   0x18
47    _reserved0: [u32; 1],                            //   0x1c
48    key0: WriteOnly<u32, Key::Register>,             //   0x20
49    key1: WriteOnly<u32, Key::Register>,             //   0x24
50    key2: WriteOnly<u32, Key::Register>,             //   0x28
51    key3: WriteOnly<u32, Key::Register>,             //   0x2c
52    key4: WriteOnly<u32, Key::Register>,             //   0x30
53    key5: WriteOnly<u32, Key::Register>,             //   0x34
54    key6: WriteOnly<u32, Key::Register>,             //   0x38
55    key7: WriteOnly<u32, Key::Register>,             //   0x3c
56    initvect0: WriteOnly<u32, InitVector::Register>, //   0x40
57    initvect1: WriteOnly<u32, InitVector::Register>, //   0x44
58    initvect2: WriteOnly<u32, InitVector::Register>, //   0x48
59    initvect3: WriteOnly<u32, InitVector::Register>, //   0x4c
60    idata: WriteOnly<u32, Data::Register>,           //   0x50
61    _reserved1: [u32; 3],                            //          0x54 - 0x5c
62    odata: ReadOnly<u32, Data::Register>,            //   0x60
63    _reserved2: [u32; 3],                            //          0x64 - 0x6c
64    drngseed: WriteOnly<u32, DrngSeed::Register>,    //   0x70
65    parameter: ReadOnly<u32, Parameter::Register>,   //   0x70
66    version: ReadOnly<u32, Version::Register>,       //   0x70
67}
68
69register_bitfields![u32,
70    Control [
71        ENABLE 0,
72        DKEYGEN 1,
73        NEWMSG 2,
74        SWSRT 8
75    ],
76    Mode [
77        CTYPE4  OFFSET(19) NUMBITS(1) [],
78        CTYPE3  OFFSET(18) NUMBITS(1) [],
79        CTYPE2  OFFSET(17) NUMBITS(1) [],
80        CTYPE1  OFFSET(16) NUMBITS(1) [],
81        CFBS    OFFSET(8)  NUMBITS(3) [
82            Bits128 = 0,
83            Bits64  = 1,
84            Bits32  = 2,
85            Bits16  = 3,
86            Bits8   = 4
87        ],
88        OPMODE  OFFSET(4)  NUMBITS(3) [
89            ECB     = 0,
90            CBC     = 1,
91            CFB     = 2,
92            OFB     = 3,
93            CTR     = 4
94        ],
95        DMA     OFFSET(3)  NUMBITS(1) [],
96        ENCRYPT OFFSET(0)  NUMBITS(1) []
97    ],
98    DataBuf [
99        ODATAW OFFSET(4)  NUMBITS(2) [],
100        IDATAW OFFSET(0)  NUMBITS(2) []
101    ],
102    Status [
103        IBUFRDY 16,
104        ODATARDY 0
105    ],
106    Interrupt [
107        IBUFRDY 16,
108        ODATARDY 0
109    ],
110    Key [
111        KEY OFFSET(0)  NUMBITS(32) []
112    ],
113    InitVector [
114        VECTOR OFFSET(0)  NUMBITS(32) []
115    ],
116    Data [
117        DATA OFFSET(0)  NUMBITS(32) []
118    ],
119    DrngSeed [
120        SEED OFFSET(0)  NUMBITS(32) []
121    ],
122    Parameter [
123        CTRMEAS OFFSET(8)  NUMBITS(1) [
124            Implemented = 0,
125            NotImplemented = 1
126        ],
127        OPMODE  OFFSET(2)  NUMBITS(3) [
128            ECB = 0,
129            ECB_CBC = 1,
130            ECB_CBC_CFB = 2,
131            ECB_CBC_CFB_OFB = 3,
132            ECB_CBC_CFB_OFB_CTR = 4
133        ],
134        MAXKEYSIZE OFFSET(0)  NUMBITS(2) [
135            Bits128 = 0,
136            Bits192 = 1,
137            Bits256 = 2
138        ]
139    ],
140    Version [
141        VARIANT  OFFSET(16)  NUMBITS(4),
142        VERSION  OFFSET(0)   NUMBITS(12)
143    ]
144];
145
146// Section 7.1 of datasheet
147const AES_BASE: StaticRef<AesRegisters> =
148    unsafe { StaticRef::new(0x400B0000 as *const AesRegisters) };
149
150pub struct Aes<'a> {
151    registers: StaticRef<AesRegisters>,
152
153    client: OptionalCell<&'a dyn hil::symmetric_encryption::Client<'a>>,
154    source: TakeCell<'static, [u8]>,
155    dest: TakeCell<'static, [u8]>,
156
157    // An index into `source` (or `dest` if that does not exist),
158    // marking how much data has been written to the AESA
159    write_index: Cell<usize>,
160
161    // An index into `dest`, marking how much data has been read back from the AESA
162    read_index: Cell<usize>,
163
164    // The index just after the last byte of `dest` that should receive encrypted output
165    stop_index: Cell<usize>,
166}
167
168impl<'a> Aes<'a> {
169    pub fn new() -> Aes<'a> {
170        Aes {
171            registers: AES_BASE,
172            client: OptionalCell::empty(),
173            source: TakeCell::empty(),
174            dest: TakeCell::empty(),
175            write_index: Cell::new(0),
176            read_index: Cell::new(0),
177            stop_index: Cell::new(0),
178        }
179    }
180
181    fn enable_clock(&self) {
182        pm::enable_clock(pm::Clock::HSB(pm::HSBClock::AESA));
183        scif::generic_clock_enable_divided(
184            scif::GenericClock::GCLK4,
185            scif::ClockSource::CLK_CPU,
186            1,
187        );
188        scif::generic_clock_enable(scif::GenericClock::GCLK4, scif::ClockSource::CLK_CPU);
189    }
190
191    fn disable_clock(&self) {
192        scif::generic_clock_disable(scif::GenericClock::GCLK4);
193        pm::disable_clock(pm::Clock::HSB(pm::HSBClock::AESA));
194    }
195
196    fn enable_interrupts(&self) {
197        self.registers
198            .ier
199            .write(Interrupt::IBUFRDY.val(1) + Interrupt::ODATARDY.val(1));
200    }
201
202    fn disable_interrupts(&self) {
203        self.registers
204            .idr
205            .write(Interrupt::IBUFRDY.val(1) + Interrupt::ODATARDY.val(1));
206    }
207
208    fn disable_input_interrupt(&self) {
209        // Tell the AESA not to send an interrupt looking for more input
210        self.registers.idr.write(Interrupt::IBUFRDY.val(1));
211    }
212
213    fn busy(&self) -> bool {
214        // Are any interrupts set, meaning an encryption operation
215        // is in progress?
216        (self.registers.imr.read(Interrupt::IBUFRDY) | self.registers.imr.read(Interrupt::ODATARDY))
217            != 0
218    }
219
220    fn set_mode(&self, encrypting: bool, mode: ConfidentialityMode) {
221        let encrypt = u32::from(encrypting);
222        let dma = 0;
223        self.registers.mode.write(
224            Mode::ENCRYPT.val(encrypt)
225                + Mode::DMA.val(dma)
226                + Mode::OPMODE.val(mode as u32)
227                + Mode::CTYPE4.val(1)
228                + Mode::CTYPE3.val(1)
229                + Mode::CTYPE2.val(1)
230                + Mode::CTYPE1.val(1),
231        );
232    }
233
234    fn input_buffer_ready(&self) -> bool {
235        self.registers.sr.read(Status::IBUFRDY) != 0
236    }
237
238    fn output_data_ready(&self) -> bool {
239        self.registers.sr.read(Status::ODATARDY) != 0
240    }
241
242    fn try_set_indices(&self, start_index: usize, stop_index: usize) -> bool {
243        stop_index.checked_sub(start_index).is_some_and(|sublen| {
244            sublen % AES128_BLOCK_SIZE == 0 && {
245                self.source.map_or_else(
246                    || {
247                        // The destination buffer is also the input
248                        if self.dest.map_or(false, |dest| stop_index <= dest.len()) {
249                            self.write_index.set(start_index);
250                            self.read_index.set(start_index);
251                            self.stop_index.set(stop_index);
252                            true
253                        } else {
254                            false
255                        }
256                    },
257                    |source| {
258                        if sublen == source.len()
259                            && self.dest.map_or(false, |dest| stop_index <= dest.len())
260                        {
261                            // We will start writing to the AES from the beginning of `source`,
262                            // and end at its end
263                            self.write_index.set(0);
264
265                            // We will start reading from the AES into `dest` at `start_index`,
266                            // and continue until `stop_index`
267                            self.read_index.set(start_index);
268                            self.stop_index.set(stop_index);
269                            true
270                        } else {
271                            false
272                        }
273                    },
274                )
275            }
276        })
277    }
278
279    // Copy a block from the request buffer to the AESA input register,
280    // if there is a block left in the buffer.  Either way, this function
281    // returns true if more blocks remain to send.
282    fn write_block(&self) -> bool {
283        self.source.map_or_else(
284            || {
285                // The source and destination are the same buffer
286                self.dest.map_or_else(
287                    || {
288                        debug!("Called write_block() with no data");
289                        false
290                    },
291                    |dest| {
292                        let index = self.write_index.get();
293                        let more = index + AES128_BLOCK_SIZE <= self.stop_index.get();
294                        if !more {
295                            return false;
296                        }
297                        for i in 0..4 {
298                            let mut v = dest[index + (i * 4) + 0] as usize;
299                            v |= (dest[index + (i * 4) + 1] as usize) << 8;
300                            v |= (dest[index + (i * 4) + 2] as usize) << 16;
301                            v |= (dest[index + (i * 4) + 3] as usize) << 24;
302                            self.registers.idata.set(v as u32);
303                        }
304                        self.write_index.set(index + AES128_BLOCK_SIZE);
305
306                        self.write_index.get() + AES128_BLOCK_SIZE <= self.stop_index.get()
307                    },
308                )
309            },
310            |source| {
311                let index = self.write_index.get();
312
313                let more = index + AES128_BLOCK_SIZE <= source.len();
314                if !more {
315                    return false;
316                }
317
318                for i in 0..4 {
319                    let mut v = source[index + (i * 4) + 0] as usize;
320                    v |= (source[index + (i * 4) + 1] as usize) << 8;
321                    v |= (source[index + (i * 4) + 2] as usize) << 16;
322                    v |= (source[index + (i * 4) + 3] as usize) << 24;
323                    self.registers.idata.set(v as u32);
324                }
325
326                self.write_index.set(index + AES128_BLOCK_SIZE);
327
328                self.write_index.get() + AES128_BLOCK_SIZE <= source.len()
329            },
330        )
331    }
332
333    // Copy a block from the AESA output register back into the request buffer
334    // if there is any room left.  Return true if we are still waiting for more
335    // blocks after this
336    fn read_block(&self) -> bool {
337        self.dest.map_or_else(
338            || {
339                debug!("Called read_block() with no data");
340                false
341            },
342            |dest| {
343                let index = self.read_index.get();
344                let more = index + AES128_BLOCK_SIZE <= self.stop_index.get();
345                if !more {
346                    return false;
347                }
348
349                for i in 0..4 {
350                    let v = self.registers.odata.get();
351                    dest[index + (i * 4) + 0] = (v >> 0) as u8;
352                    dest[index + (i * 4) + 1] = (v >> 8) as u8;
353                    dest[index + (i * 4) + 2] = (v >> 16) as u8;
354                    dest[index + (i * 4) + 3] = (v >> 24) as u8;
355                }
356
357                self.read_index.set(index + AES128_BLOCK_SIZE);
358
359                self.read_index.get() + AES128_BLOCK_SIZE <= self.stop_index.get()
360            },
361        )
362    }
363
364    /// Handle an interrupt, which will indicate either that the AESA's input
365    /// buffer is ready for more data, or that it has completed a block of output
366    /// for us to consume
367    pub fn handle_interrupt(&self) {
368        if !self.busy() {
369            // Ignore errant interrupts, in case it's possible for the AES interrupt flag
370            // to be set again while we are in this handler.
371            return;
372        }
373
374        if self.input_buffer_ready() {
375            // The AESA says it is ready to receive another block
376
377            if !self.write_block() {
378                // We've now written the entirety of the request buffer,
379                // so unsubscribe from input interrupts
380                self.disable_input_interrupt();
381            }
382        }
383
384        if self.output_data_ready() {
385            // The AESA says it has a completed block to give us
386
387            if !self.read_block() {
388                // We've read back all the blocks, so unsubscribe from
389                // all interrupts
390                self.disable_interrupts();
391
392                // Alert the client of the completion
393                self.client.map(|client| {
394                    client.crypt_done(self.source.take(), self.dest.take().unwrap());
395                });
396            }
397        }
398    }
399}
400
401impl<'a> hil::symmetric_encryption::AES128<'a> for Aes<'a> {
402    fn enable(&self) {
403        self.enable_clock();
404        self.registers.ctrl.write(Control::ENABLE.val(1));
405    }
406
407    fn disable(&self) {
408        self.registers.ctrl.set(0);
409        self.disable_clock();
410    }
411
412    fn set_client(&'a self, client: &'a dyn hil::symmetric_encryption::Client<'a>) {
413        self.client.set(client);
414    }
415
416    fn set_key(&self, key: &[u8]) -> Result<(), ErrorCode> {
417        if key.len() != AES128_KEY_SIZE {
418            return Err(ErrorCode::INVAL);
419        }
420
421        for i in 0..4 {
422            let mut k = key[i * 4 + 0] as usize;
423            k |= (key[i * 4 + 1] as usize) << 8;
424            k |= (key[i * 4 + 2] as usize) << 16;
425            k |= (key[i * 4 + 3] as usize) << 24;
426            match i {
427                0 => self.registers.key0.set(k as u32),
428                1 => self.registers.key1.set(k as u32),
429                2 => self.registers.key2.set(k as u32),
430                3 => self.registers.key3.set(k as u32),
431                _ => {}
432            }
433        }
434
435        Ok(())
436    }
437
438    fn set_iv(&self, iv: &[u8]) -> Result<(), ErrorCode> {
439        if iv.len() != AES128_BLOCK_SIZE {
440            return Err(ErrorCode::INVAL);
441        }
442
443        // Set the initial value from the array.
444        for i in 0..4 {
445            let mut c = iv[i * 4 + 0] as usize;
446            c |= (iv[i * 4 + 1] as usize) << 8;
447            c |= (iv[i * 4 + 2] as usize) << 16;
448            c |= (iv[i * 4 + 3] as usize) << 24;
449            match i {
450                0 => self.registers.initvect0.set(c as u32),
451                1 => self.registers.initvect1.set(c as u32),
452                2 => self.registers.initvect2.set(c as u32),
453                3 => self.registers.initvect3.set(c as u32),
454                _ => {}
455            }
456        }
457
458        Ok(())
459    }
460
461    fn start_message(&self) {
462        if self.busy() {
463            return;
464        }
465        self.registers
466            .ctrl
467            .write(Control::NEWMSG.val(1) + Control::ENABLE.val(1));
468    }
469
470    fn crypt(
471        &self,
472        source: Option<&'static mut [u8]>,
473        dest: &'static mut [u8],
474        start_index: usize,
475        stop_index: usize,
476    ) -> Option<(
477        Result<(), ErrorCode>,
478        Option<&'static mut [u8]>,
479        &'static mut [u8],
480    )> {
481        if self.busy() {
482            Some((Err(ErrorCode::BUSY), source, dest))
483        } else {
484            self.source.put(source);
485            self.dest.replace(dest);
486            if self.try_set_indices(start_index, stop_index) {
487                self.enable_interrupts();
488                None
489            } else {
490                Some((
491                    Err(ErrorCode::INVAL),
492                    self.source.take(),
493                    self.dest.take().unwrap(),
494                ))
495            }
496        }
497    }
498}
499
500impl hil::symmetric_encryption::AES128Ctr for Aes<'_> {
501    fn set_mode_aes128ctr(&self, encrypting: bool) -> Result<(), ErrorCode> {
502        self.set_mode(encrypting, ConfidentialityMode::CTR);
503        Ok(())
504    }
505}
506
507impl hil::symmetric_encryption::AES128CBC for Aes<'_> {
508    fn set_mode_aes128cbc(&self, encrypting: bool) -> Result<(), ErrorCode> {
509        self.set_mode(encrypting, ConfidentialityMode::CBC);
510        Ok(())
511    }
512}
513
514impl kernel::hil::symmetric_encryption::AES128ECB for Aes<'_> {
515    fn set_mode_aes128ecb(&self, encrypting: bool) -> Result<(), ErrorCode> {
516        self.set_mode(encrypting, ConfidentialityMode::ECB);
517        Ok(())
518    }
519}