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                        let more =
307                            self.write_index.get() + AES128_BLOCK_SIZE <= self.stop_index.get();
308                        more
309                    },
310                )
311            },
312            |source| {
313                let index = self.write_index.get();
314
315                let more = index + AES128_BLOCK_SIZE <= source.len();
316                if !more {
317                    return false;
318                }
319
320                for i in 0..4 {
321                    let mut v = source[index + (i * 4) + 0] as usize;
322                    v |= (source[index + (i * 4) + 1] as usize) << 8;
323                    v |= (source[index + (i * 4) + 2] as usize) << 16;
324                    v |= (source[index + (i * 4) + 3] as usize) << 24;
325                    self.registers.idata.set(v as u32);
326                }
327
328                self.write_index.set(index + AES128_BLOCK_SIZE);
329
330                let more = self.write_index.get() + AES128_BLOCK_SIZE <= source.len();
331                more
332            },
333        )
334    }
335
336    // Copy a block from the AESA output register back into the request buffer
337    // if there is any room left.  Return true if we are still waiting for more
338    // blocks after this
339    fn read_block(&self) -> bool {
340        self.dest.map_or_else(
341            || {
342                debug!("Called read_block() with no data");
343                false
344            },
345            |dest| {
346                let index = self.read_index.get();
347                let more = index + AES128_BLOCK_SIZE <= self.stop_index.get();
348                if !more {
349                    return false;
350                }
351
352                for i in 0..4 {
353                    let v = self.registers.odata.get();
354                    dest[index + (i * 4) + 0] = (v >> 0) as u8;
355                    dest[index + (i * 4) + 1] = (v >> 8) as u8;
356                    dest[index + (i * 4) + 2] = (v >> 16) as u8;
357                    dest[index + (i * 4) + 3] = (v >> 24) as u8;
358                }
359
360                self.read_index.set(index + AES128_BLOCK_SIZE);
361
362                let more = self.read_index.get() + AES128_BLOCK_SIZE <= self.stop_index.get();
363                more
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::AES128<'a> 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() != AES128_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::AES128Ctr for Aes<'_> {
505    fn set_mode_aes128ctr(&self, encrypting: bool) -> Result<(), ErrorCode> {
506        self.set_mode(encrypting, ConfidentialityMode::CTR);
507        Ok(())
508    }
509}
510
511impl hil::symmetric_encryption::AES128CBC for Aes<'_> {
512    fn set_mode_aes128cbc(&self, encrypting: bool) -> Result<(), ErrorCode> {
513        self.set_mode(encrypting, ConfidentialityMode::CBC);
514        Ok(())
515    }
516}
517
518impl kernel::hil::symmetric_encryption::AES128ECB for Aes<'_> {
519    fn set_mode_aes128ecb(&self, encrypting: bool) -> Result<(), ErrorCode> {
520        self.set_mode(encrypting, ConfidentialityMode::ECB);
521        Ok(())
522    }
523}