Skip to content

Commit

Permalink
Merge #3092
Browse files Browse the repository at this point in the history
3092: capsules: Add support for AES GCM r=bradjc a=alistair23

### Pull Request Overview

This PR adds a new aes_gcm capsule. This capsule exposes [AES-GCM](https://en.wikipedia.org/wiki/AES-GCM-SIV) support if the hardware doesn't actually have it.

We implement AES GCM using other supported AES operations and with a software implementation of ghash.

This is similar to the existing virtual_aes_ccm capsule, except without virtulisation.

AES-GCM is commonly used in [TLS](https://blog.mozilla.org/security/2017/09/29/improving-aes-gcm-performance/). It isn't commonly used in embedded systems, but it's still a good example I think.

### Testing Strategy

Running the OpenTitan tests

### TODO or Help Wanted

This PR adds an external dependency!

This PR adds a dependency on the [ghash crate](https://github.com/RustCrypto/universal-hashes/tree/master/ghash) as part of Rust-crypto.

We are seeing more and more requirements for cryptographic operations in Tock, which means we are also seeing more and more software implementations of them.

Tock already has a SHA256 and CRC32 software implementation. It's not unreasonable that RSA becomes more common with the cryptographic app IDs as well.

I wanted to start the discussion about allowing Rust-crypto crates as capsules. Re-implementing a crypto library ourselves seem very risky, so if we do want software implementations Rust-crypto would be the way to go. I'm not convinced one way or the other, I just wanted to get some feedback on how people feel.

The Rust-crypto crates are well respected, have been audited and match the Tock software license

### Documentation Updated

- [X] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [X] Ran `make prepush`.


Co-authored-by: Alistair Francis <alistair.francis@wdc.com>
  • Loading branch information
bors[bot] and alistair23 committed Jun 7, 2023
2 parents 07de9e7 + c155d68 commit f5bd104
Show file tree
Hide file tree
Showing 10 changed files with 739 additions and 46 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ members = [
"boards/qemu_rv32_virt",
"boards/swervolf",
"boards/weact_f401ccu6/",
"capsules/aes_gcm",
"capsules/core",
"capsules/extra",
"chips/apollo3",
Expand Down
1 change: 1 addition & 0 deletions boards/opentitan/earlgrey-cw310/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tock-tbf = { path = "../../../libraries/tock-tbf" }

capsules-core = { path = "../../../capsules/core" }
capsules-extra = { path = "../../../capsules/extra" }
capsules-aes-gcm = { path = "../../../capsules/aes_gcm" }


[features]
Expand Down
50 changes: 35 additions & 15 deletions boards/opentitan/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use crate::hil::symmetric_encryption::AES128_BLOCK_SIZE;
use crate::otbn::OtbnComponent;
use capsules_aes_gcm::aes_gcm;
use capsules_core::virtualizers::virtual_aes_ccm;
use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
use capsules_core::virtualizers::virtual_hmac::VirtualMuxHmac;
Expand Down Expand Up @@ -79,9 +80,13 @@ static mut TICKV: Option<
capsules_extra::sip_hash::SipHasher24<'static>,
>,
> = None;
// Test access to AES CCM
static mut AES: Option<&virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>> =
None;
// Test access to AES
static mut AES: Option<
&aes_gcm::Aes128Gcm<
'static,
virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
>,
> = None;
// Test access to SipHash
static mut SIPHASH: Option<&capsules_extra::sip_hash::SipHasher24<'static>> = None;
// Test access to RSA
Expand Down Expand Up @@ -158,7 +163,10 @@ struct EarlGrey {
rng: &'static capsules_core::rng::RngDriver<'static>,
aes: &'static capsules_extra::symmetric_encryption::aes::AesDriver<
'static,
virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
aes_gcm::Aes128Gcm<
'static,
virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
>,
>,
kv_driver: &'static capsules_extra::kv_driver::KVSystemDriver<
'static,
Expand Down Expand Up @@ -632,9 +640,6 @@ unsafe fn setup() -> (

const CRYPT_SIZE: usize = 7 * AES128_BLOCK_SIZE;

let aes_source_buffer = static_init!([u8; 16], [0; 16]);
let aes_dest_buffer = static_init!([u8; CRYPT_SIZE], [0; CRYPT_SIZE]);

let ccm_mux = static_init!(
virtual_aes_ccm::MuxAES128CCM<'static, earlgrey::aes::Aes<'static>>,
virtual_aes_ccm::MuxAES128CCM::new(&peripherals.aes)
Expand All @@ -643,20 +648,35 @@ unsafe fn setup() -> (
peripherals.aes.set_client(ccm_mux);

let crypt_buf1 = static_init!([u8; CRYPT_SIZE], [0x00; CRYPT_SIZE]);
let ccm_client1 = static_init!(
let ccm_client = static_init!(
virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
virtual_aes_ccm::VirtualAES128CCM::new(ccm_mux, crypt_buf1)
);
ccm_client1.setup();
// ccm_mux.set_client(ccm_client1);
ccm_client.setup();

let aes_source_buffer = static_init!([u8; 16], [0; 16]);
let aes_dest_buffer = static_init!([u8; CRYPT_SIZE], [0; CRYPT_SIZE]);

let crypt_buf2 = static_init!([u8; CRYPT_SIZE], [0x00; CRYPT_SIZE]);
let gcm_client = static_init!(
aes_gcm::Aes128Gcm<
'static,
virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
>,
aes_gcm::Aes128Gcm::new(ccm_client, crypt_buf2)
);
ccm_client.set_client(gcm_client);

let aes = static_init!(
capsules_extra::symmetric_encryption::aes::AesDriver<
'static,
virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
aes_gcm::Aes128Gcm<
'static,
virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
>,
>,
capsules_extra::symmetric_encryption::aes::AesDriver::new(
ccm_client1,
gcm_client,
aes_source_buffer,
aes_dest_buffer,
board_kernel.create_grant(
Expand All @@ -666,7 +686,7 @@ unsafe fn setup() -> (
)
);

AES = Some(ccm_client1);
AES = Some(gcm_client);

#[cfg(test)]
{
Expand All @@ -678,8 +698,8 @@ unsafe fn setup() -> (
SHA256SOFT = Some(sha_soft);
}

hil::symmetric_encryption::AES128CCM::set_client(ccm_client1, aes);
hil::symmetric_encryption::AES128::set_client(ccm_client1, aes);
hil::symmetric_encryption::AES128GCM::set_client(gcm_client, aes);
hil::symmetric_encryption::AES128::set_client(gcm_client, ccm_client);

// These symbols are defined in the linker script.
extern "C" {
Expand Down
54 changes: 49 additions & 5 deletions boards/opentitan/src/tests/aes_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@

use crate::tests::run_kernel_op;
use crate::{AES, PERIPHERALS};
use capsules_aes_gcm::aes_gcm::Aes128Gcm;
use capsules_core::virtualizers::virtual_aes_ccm;
use capsules_extra::test::aes::{TestAes128Cbc, TestAes128Ctr, TestAes128Ecb};
use capsules_extra::test::aes_ccm::Test;
use capsules_extra::test::aes_ccm;
use capsules_extra::test::aes_gcm;
use earlgrey::aes::Aes;
use kernel::debug;
use kernel::hil::symmetric_encryption::{AES128, AES128_BLOCK_SIZE, AES128_KEY_SIZE};
Expand All @@ -33,13 +35,55 @@ fn run_aes128_ccm() {
}

unsafe fn static_init_test_ccm(
aes: &'static virtual_aes_ccm::VirtualAES128CCM<'static, Aes>,
) -> &'static Test<'static, virtual_aes_ccm::VirtualAES128CCM<'static, Aes<'static>>> {
aes: &'static Aes128Gcm<'static, virtual_aes_ccm::VirtualAES128CCM<'static, Aes<'static>>>,
) -> &'static aes_ccm::Test<
'static,
Aes128Gcm<'static, virtual_aes_ccm::VirtualAES128CCM<'static, Aes<'static>>>,
> {
let buf = static_init!([u8; 4 * AES128_BLOCK_SIZE], [0; 4 * AES128_BLOCK_SIZE]);

static_init!(
Test<'static, virtual_aes_ccm::VirtualAES128CCM<'static, Aes>>,
Test::new(aes, buf)
aes_ccm::Test<
'static,
Aes128Gcm<'static, virtual_aes_ccm::VirtualAES128CCM<'static, Aes<'static>>>,
>,
aes_ccm::Test::new(aes, buf)
)
}

#[test_case]
fn run_aes128_gcm() {
debug!("check run AES128 GCM... ");
run_kernel_op(100);

unsafe {
let aes = AES.unwrap();

let t = static_init_test_gcm(&aes);
kernel::hil::symmetric_encryption::AES128GCM::set_client(aes, t);

#[cfg(feature = "hardware_tests")]
t.run();
}
run_kernel_op(10000);
debug!(" [ok]");
run_kernel_op(100);
}

unsafe fn static_init_test_gcm(
aes: &'static Aes128Gcm<'static, virtual_aes_ccm::VirtualAES128CCM<'static, Aes<'static>>>,
) -> &'static aes_gcm::Test<
'static,
Aes128Gcm<'static, virtual_aes_ccm::VirtualAES128CCM<'static, Aes<'static>>>,
> {
let buf = static_init!([u8; 9 * AES128_BLOCK_SIZE], [0; 9 * AES128_BLOCK_SIZE]);

static_init!(
aes_gcm::Test<
'static,
Aes128Gcm<'static, virtual_aes_ccm::VirtualAES128CCM<'static, Aes<'static>>>,
>,
aes_gcm::Test::new(aes, buf)
)
}

Expand Down
15 changes: 15 additions & 0 deletions capsules/aes_gcm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Licensed under the Apache License, Version 2.0 or the MIT License.
# SPDX-License-Identifier: Apache-2.0 OR MIT
# Copyright Western Digital 2023.

[package]
name = "capsules-aes-gcm"
version.workspace = true
authors.workspace = true
edition.workspace = true

[dependencies]
kernel = { path = "../../kernel" }
enum_primitive = { path = "../../libraries/enum_primitive" }
tickv = { path = "../../libraries/tickv" }
ghash = "0.4.4"
37 changes: 37 additions & 0 deletions capsules/aes_gcm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
AES GCM Capsule
===============

This crate contains software support for
[AES-GCM](https://en.wikipedia.org/wiki/AES-GCM-SIV).
This capsule doesn't perform any AES operations, instead it relies on
existing implmenetations to perform the AES operations and instead manages
the operations and hashing to support GCM.

This capsule uses the extenal
[ghash crate](https://github.com/RustCrypto/universal-hashes/tree/master/ghash)
as part of Rust-crypto to implement AES GCM on top of existing AES
implementions.

## Cargo tree

```
capsules-aes-gcm v0.1.0 (/var/mnt/scratch/alistair/software/tock/tock/capsules/aes_gcm)
├── enum_primitive v0.1.0 (/var/mnt/scratch/alistair/software/tock/tock/libraries/enum_primitive)
├── ghash v0.4.4
│ ├── opaque-debug v0.3.0
│ └── polyval v0.5.3
│ ├── cfg-if v1.0.0
│ ├── cpufeatures v0.2.7
│ ├── opaque-debug v0.3.0
│ └── universal-hash v0.4.1
│ ├── generic-array v0.14.7
│ │ └── typenum v1.16.0
│ │ [build-dependencies]
│ │ └── version_check v0.9.4
│ └── subtle v2.4.1
├── kernel v0.1.0 (/var/mnt/scratch/alistair/software/tock/tock/kernel)
│ ├── tock-cells v0.1.0 (/var/mnt/scratch/alistair/software/tock/tock/libraries/tock-cells)
│ ├── tock-registers v0.8.1 (/var/mnt/scratch/alistair/software/tock/tock/libraries/tock-register-interface)
│ └── tock-tbf v0.1.0 (/var/mnt/scratch/alistair/software/tock/tock/libraries/tock-tbf)
└── tickv v1.0.0 (/var/mnt/scratch/alistair/software/tock/tock/libraries/tickv)
```
Loading

0 comments on commit f5bd104

Please sign in to comment.