Skip to main content

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