|
The contents of this repository and linked repositories are solely for research purposes and may contain software with vulnerabilities, such as outdated libraries. Do not use in production. |
C3-Simulator is a Simics-based functional simulator for the X86 C3 processor, including library and kernel support for pointer and data encryption, optional compile-time instrumentation, debugger enabling, and scripting for running tests.
ℹ️
|
This material is based upon work supported by the Naval Information Warfare Center Pacific and the Defense Advanced Research Project Agency under Prototype Other Transaction Agreement No. N66001-23-9-4004. Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the Naval Information Warfare Center Pacific or the Defense Advanced Research Project Agency. |
To use the C3 simulator you only need Docker and the public Simics packages.
This allows you to build the environments and run Simics from within the Docker
container. While most builds are using Make on the host you can also open a
shell to Docker with make c3_docker_shell
. To use the Simics GUI you need to
run Simics on your host machine, see Installing and running Simics on host.
If you need to use a network proxy, please see Proxy configuration.
See C3 protected user-space applications, C3 protected Linux kernel, and C3 protected EDK2 for details on running alternate configurations and building the C3 protected Linux kernel or EDK2 firmware.
See C3 development environment for more details on modifying and experimenting with the C3 Simics model and associated software artifacts. For more specific details on the Simics model, see C3 Simics simulation model.
To setup Simics, setup the build environment, and generate Simics checkpoints,
you need to manually download the Simics packages, clone the C3 simulator code
and then place the Simics packages in the scripts/docker
folder:
# Clone repository
git clone --recurse-submodules https://github.com/IntelLabs/c3-simulator.git c3-simulator
cd c3-simulator
# Copy simics packages (or put files in /opt/simics/simics_packages_public)
cp ~/Downloads/intel-simics-package-manager-1.9.4-linux64.tar.gz \
~/Downloads/simics-6-packages-2024-25-linux64.tar.gz \
scripts/dokcer
# Pre-build Docker container (may take >1h first time)
make c3_docker
You can also setup the Simics project on your host and run ./simics
and other
scripts directly on your host machine. But note that you must use the Simics
version used by the Docker container, and install other dependencies (See
Installing and running Simics on host for more details):
make simics_setup SIMICS_BIN=[CUSTOM_SIMICS_PATH]
To run the gem5 you can run:
./run-tests.sh demo performance_simulator
See github.com/IntelLabs/c3-perf-simulator for more details and the related source code.
Once you have configured the project for use with Docker, you can use the following commands to build a checkpoint and run Simics within the container:
# Generate checkpoints/cc_kernel.ckpt Simics checkpoint (with C3-aware kernel)
make cc_kernel
# Enter docker container (Optional if running Simics on host)
make c3_docker_shell
# To run simple workload (e.g., `microbenchmarks/hello.cpp`):
docker> ./simics scripts/runworkload_common.simics \
checkpoint=checkpoints/cc_llvm.ckpt \
model=c3 \
src_file=microbenchmarks/hello.cpp
# To run pre-compiled binary
docker> g++ microbenchmarks/hello.cpp -o a.out
docker> ./simics scripts/runworkload_common.simics \
checkpoint=checkpoints/cc_llvm.ckpt \
model=c3 \
nobuild=TRUE \
src_file=a.out
See C3 protected user-space applications for more details.
To build and run C3-hardened Linux kernel, run:
make c3_docker-linux_buildroot
See C3 protected Linux kernel for more details.
To boot up a C3-hardened EDK2 you will need to build EDK2 and the Buildroot Linux environment that is going to be booted under EDK2. The following commands build and boot the environment, and open up a Linux shell booted under the C3-hardened EDK2:
# Build and run EDK2 (note this will take >1h the first time)
make edk2_all
make edk2_run
# or:
./run-tests.sh demo edk2
See C3 protected EDK2 for more details.
The C3 LLVM include a clang-tidy to help optimize code for C3 intra-object protections by suggesting various code changes to achieve optimal memory layouts. Note that while vanilla C3 does not require memory layout changes, the intra-object protection uses tripwires that require memory layout changes; which is what the C3 clang-tidy helps with.
To run demo and see examples of suggested changes:
make c3_docker-demo-clang_tidy.sh
C3 can be used to detect uninitialized memory reads, using integrity check values.
To run demo:
make c3_docker-demo-cwe457.sh
C3 can be used to protect the stack by setting the stack pointer register to a cryptographic address (CA). In addition to providing isolation from other memory regions, this allows the unwinder to utilize the CA for additional checks during unwinding.
To view a demo of this in operation, run:
make c3_docker-demo-castack_and_unwind_01
The tests are currently configured to use LLVM’s libunwind, consequently you
must use an LLVM checkpoint to run unit tests (e.g., checkpoints/cc_llvm.ckpt as described
above). You may also run with a C3-aware kernel checkpoint (e.g.,
checkpoints/cc_kernel.ckpt), in which case you need to add --have-kernel
. You can run all
tests directly with pytest:
# With non-kernel checkpoint:
pytest -n -v python_tests --checkpoint checkpoints/cc_llvm.ckpt [--model ]*
# With a C3-aware kernel:
pytest -n -v python_tests --checkpoint checkpoints/cc_kernel.ckpt --have-kernel [--model ]*
Common options:
--checkpoint PATH |
Set the checkpoint to use |
--model |
Run tests only with the specified model. Can specify multiple models by appending '--model <model_name>' for each model. The 'c3-integrity' model will run on the c3 but configure it to use integrity |
--nomodel |
Exclude specific models from the run. Useful when leaving out |
-d|--dist=load |
Load-balance tests. |
--have-kernel |
Run C3-kernel dependent tests |
You can also run individual unit tests. To do so, you will need some additional
options: include_folders
to copy the unit test include folder, and 2) add the
unit_tests include and -DC3_MODEL define to `gcc_flags
:
./simics unit_tests/runtest_common.simics \
checkpoint=checkpoints/cc_llvm.ckpt \
model=c3 \
src_file=unit_tests/common/gtest_hello.cpp
To test different configuration (e.g. integrity), the test scripts support pseudo models that configure the underlying model in specific ways. Currently these models are:
c3-integrity |
Test C3 integrity. |
c3-integrity-intra |
Test C3 intra-object integrity. |
c3-castack |
Test C3 CAStack. |
c3-nowrap |
Test C3 glibc NOWRAP variant. |
Note that the checks may have dependencies to specific checkpoints (e.g., the c3-nowrap model requires a nowrap checkpoint). For instance, to test C3 integrity, run:
pytest -v python_tests/test_unit.py \
--checkpoint checkpoints/cc_llvm.ckpt \
--model c3-integrity
You can also run single modified tests by providing the appropriate commands to the test script:
./simics unit_tests/runtest_common.simics \
checkpoint=checkpoints/cc_llvm.ckpt \
model=c3 \
enable_integrity=TRUE \
src_file=unit_tests/common/gtest_hello.cpp
To enable ICV-based intra-object tripwires, you need to use the C3-enabled LLVM/Clang that is included in any checkpoint with the C3 LLVM installed.
# For single unit tests with intra-object integrity:
./simics unit_tests/runtest_common.simics \
checkpoint=checkpoints/cc_kernel.ckpt \
model=c3 \
enable_integrity=TRUE \
compiler="/home/simics/llvm/llvm_install/bin/clang++" \
gcc_flags="-fuse-ld=lld -finsert-intraobject-tripwires=all" \
src_file=unit_tests/common/gtest_hello.cpp
# For unit tests via pytest:
pytest -v python_tests/test_unit.py --checkpoint checkpoints/cc_kernel.ckpt --have-kernel --model c3-integrity-intra
The test runner automatically discovers tests in the unit tests
folder based
on header labels specified at the top of the file. Starting from the first line,
all lines starting with //
are considered part of the test header. Any files
that contain the label // model: <enabled_models>
is interpreted as a unit
test.
An up-to-date list of recognized labels can be found in the
python_tests/test_unit.py
file, but some common labels are:
model |
Can be * to indicate all models, or a list of specific models. |
need_kernel |
The test requires the C3-aware kernel. |
no_kernel |
The test is not compatible with the C3-aware kernel. |
nomodel |
List of models to exclude from testing. |
should_fail |
The correct behavior of the test is to fail (i.e., exit with non-zero). This is typical for tests that test detection error conditions such as buffer overflows. |
cxx_flags |
Additional flags needed when compiling the test. |
simics_args |
Additional arguments to pass to Simics when running test. |
xfail |
Mark test as xfail for listed models. |
C3 protections have been evaluated using a subset of the Juliet test suite. To replicate those results, you can run the following commands.
# Build necessary checkpoints for the Juliet benchmarks (if not already done)
make cc_kernel
make c3_docker-ckpt-cc_llvm_1b_ovf
# Baseline for heap vulnerabilities (without C3 protections)
make c3_docker-demo-juliet-native
# Baseline for stack vulnerabilities (without C3 protections)
make c3_docker-demo-juliet-native-stack
# C3-protected heap
make c3_docker-demo-juliet-c3-heap
# C3-protected heap with 1b overflow detection
make c3_docker-demo-juliet-c3-heap-align
# C3-protected stack
make c3_docker-demo-juliet-c3-stack
Alternatively, you can run all the Juliet tests with:
# Run all Juliet tests with run-tests.sh:
./run-tests.sh build
./run-tests.sh demo juliet
ℹ️
|
To run the juliet-c3-heap-align case, you need to prepare a checkpoint
with a glibc build that will effectively shift allocations to slightly higher
addresses if needed so that their ends align with the ends of the granules with
corresponding initialized Integrity Check Values (ICVs, if enabled), run make
c3_docker-ckpt-cc_llvm_1b_ovf . This configuration can detect single-byte
overflows from allocations that would otherwise be followed by padding bytes
within their last granules that may absorb overflows undetected. However, this
configuration may be incompatible with certain tests. Note also that even in the
default configuration that may absorb certain small overflows, those overflows
would not affect other allocations. Note also that shifting allocations in the
aforementioned manner results in an equivalent amount of padding bytes being
added at the beginning of the allocation.
|
We provide multiple different environments / checkpoints to test different aspects of C3. The main environments and build commands are:
Checkpoint | Build command | Description |
---|---|---|
|
|
C3 glibc, using system call shims. |
|
|
C3 glibc and LLVM, using system call shims. |
|
|
C3 glibc, LLVM, and kernel, system calls handle C3 pointers. |
The above commands will automatically build the associated software artifacts with the C3 Docker container, and then launch Simics to generate the corresponding simulation checkpoint.
You can also build individual software artifacts one-by-one with:
# To build LLVM on host
make llvm
# To build glibc (without system call shims)
make glibc
# To build glibc with system call shims
make glibc-shim
# To build linux
make linux
If you have all necessary dependencies installed (see
[Installing software dependencies]), you can also build the checkpoints and
software artifacts locally without Docker by adding the NO_DOCKER=1
option to
the make commands, e.g., make llvm NO_DOCKER=1
.
You can run C3 user-space workloads using the runworkload_common.simics
script, which is internally used for various task ranging from running unit
tests to demos. Some common options are listed below, you can use the Simics
help command to view all available options with:
./simics
help scripts/runworkload_common.simics
src_file |
Specifies the source or binary to run. (REQUIRED) |
checkpoint |
Specifies the checkpoint. (REQUIRED) |
model |
Selects the C3 model to use. (Note: lim_disp configures the LIM model to perform data displacement instead of shifting.) (Default: c3) |
break_on_exception |
If set to 1, will stop simulation on exceptions (excluding Page Fault) |
compiler |
Overrides the compiler for the workload (unless using custom
build command). To use C3 LLVM, set to
|
debug |
Set to 1 to enable Simics module debug output. |
disable_cc_env |
Suppress the CC_ENABLED=1 flag when running the workload (i.e., disables C3 heap protections). |
enable_integrity=TRUE |
Enable C3 integrity checking using ICVs. |
gcc_flags |
Additional compiler flags. |
For example, to run a workload with the c3 on the checkpoints/cc_kernel.ckpt
checkpoint, you can use the following commands (assuming you have created the
checkpoint previously with make cc_kernel
):
# Enter docker shell (optional if running Simics on host)
make c3_docker_shell
# To run simple workload (e.g., `microbenchmarks/hello.cpp`):
./simics scripts/runworkload_common.simics \
checkpoint=checkpoints/cc_kernel.ckpt \
model=c3 \
src_file=microbenchmarks/hello.cpp
# To run pre-compiled binary:
g++ microbenchmarks/hello.cpp -o a.out
./simics scripts/runworkload_common.simics \
checkpoint=checkpoints/cc_kernel.ckpt \
model=c3 \
nobuild=TRUE \
src_file=a.out
The c3_model has functional support for integrity checking. To
enable integrity support, use the enable_integrity=TRUE
option:
# For single workloads with integrity:
./simics scripts/runworkload_common.simics \
checkpoint=checkpoints/cc_kernel.ckpt \
model=c3 \
enable_integrity=TRUE \
src_file=microbenchmarks/hello.cpp
# For running pre-compiled binaries with integrity:
clang++ microbenchmarks/hello.cpp -o a.out
./simics scripts/runworkload_common.simics \
checkpoint=checkpoints/cc_kernel.ckpt \
model=c3 \
enable_integrity=TRUE \
nobuild=TRUE \
src_file=a.out
To enable ICV-based intra-object tripwires, you need to use the C3-enabled LLVM/Clang. This can be done by using the custom clang installed on a C3-kernel enabled checkpoint with (see [Custom kernel checkpoint]):
./simics scripts/runworkload_common.simics \
checkpoint=checkpoints/cc_kernel.ckpt \
model=c3 \
enable_integrity=TRUE \
compiler="/home/simics/llvm/llvm_install/bin/clang++" \
gcc_flags="-fuse-ld=lld -finsert-intraobject-tripwires=all"
src_file=microbenchmarks/hello.cpp
ℹ️
|
At present, the -finsert-intraobject-tripwires option does not support
multiple parallel compilation jobs. If compiling manually (e.g., not with the
runworkload_common.simics script), make sure to set -j1 to avoid parallel
builds.
|
The runworkload_common.simics
script has options for fine-grained control
of the Simics module behavior on integrity violations:
integrity_fault_on_read_mismatch=TRUE
integrity_break_on_read_mismatch=TRUE
integrity_fault_on_write_mismatch=TRUE
integrity_break_on_write_mismatch=TRUE
These will on launch explicitly configure the C3 Simics module with the the corresponding attribute set to true:
c30_0->integrity_break_on_read_mismatch
c30_0->integrity_fault_on_read_mismatch
c30_0->integrity_break_on_write_mismatch
c30_0->integrity_fault_on_write_mismatch
The corresponding configurations may already be set to TRUE by default depending
on the Simics model itself, particularly the faulting options that control
whether the corresponding violations should trigger a CPU general protection
fault within the simulation. However, the break
attribute configures the
module to trigger a Simics debugging breakpoint, and are not set and should
mainly be used for debugging.
All software support for resetting and clearing of ICVs is not yet implemented
(i.e., when a program abnormally terminates, the ICVs for the process' physical
memory pages may still retain ICVs). In some cases you may want to manually
reset the ICVs to run multiple workloads in the same Simics session. This can be
done with the integrity_icv_reset
attribute that is exposed via a Simics
module attribute and also within the simulation itself via C3 configurations.
This resetting functionality is implemented for research and debugging
purposes and would not be exposed in real deployments.
From the Simics shell, the ICV reset can be triggered with:
c30_0->integrity_icv_reset = TRUE
From within the simulation, this can be done with:
#include "malloc/cc_globals.h"
cc_trigger_icv_map_reset();
The Makefile targets will automatically build the C3 checkpoints and
dependencies. But you may want more fine grained control over the build process
by interacting directly with the different builds. In general, all makefile
targets can be inspected using the dry-run flag -n
, and the Simics help
functionality can show documentation for different simics script options.
Checkpoints that use a legacy kernel (e.g., checkpoints/cc_llvm.ckpt) and use system call
shims to handle system calls use Clear Linux. To update these, you can use the
dry-run flag -n
to view the commands used by the all-in-one makefile target, and
the Simics help command to view options to the scripts/update_libs.simics
:
# Check what commands would typically be run:
make -n cc_llvm NO_DOCKER=1
# View Simics help to see options for update_libs.simics:
./simics
simics> help scripts/update_libs.simics
The C3-kernel checkpoints are using a regular Ubuntu 20.04 installation but with
a custom kernel installed. This assumes you have an initial kernel checkpoint,
if not, see Create initial Ubuntu checkpoint. You can again use the dry-run
flag -n
and Simics help:
# Check what commands would typically be run:
make -n cc_kernel NO_DOCKER=1
# View Simics help to see options for update_libs.simics:
./simics
simics> help scripts/update_ubuntu_kernel.simics
To set up an Ubuntu checkpoint with a custom kernel, you first need to create a base Ubuntu checkpoint. You can generate such a checkpoint using:
./simics -batch-mode scripts/install_ubuntu.simics \
save_checkpoint=/opt/simics/checkpoints/ubuntu-20.4_latest.ckpt
ℹ️
|
The script automation relies on external services and may fail in
different environments. In this case, you may need to manually install the
checkpoint by manually following the steps in scripts/install_ubuntu.simics .
You may also need to change the proxy configuration to suit your environment.
|
Alternatively, or for troubleshooting, you can also run the Ubuntu installation
manually in the Simics graphical console. To do this, you need to install Simics
on your host machine and run Simics directly on the host (i.e., without docker).
See Installing and running Simics on host. You do not need to install other
dependencies and can still use Docker for other builds even if the initial
checkpoint is generated manually. The saved checkpoint sate should be a at a
freshly booted Linux shell and the Simics agent started (please consult
scripts/update_ubuntu_kernel.simics
).
To build LLDB with C3-coredump support run:
make llvm-lldb
This builds llvm/llvm_install/bin/lldb
. It has C3 support for loading
variables (and pointers) in C3 cryptographic address format, and will
automatically read in C3 keys from a coredump file generated by a C3-enabled
process. This requires that the coredump was generate by the C3-enabled custom
kernel (e.g., using a cc_kernel checkpoint).
The C3 protected Linux kernel can be tested using a Buildroot system image. It
uses the Linux source under ./linux
, but with a kernel configured to enable
kernel self-protection with C3 and disable C3 user-space support.
# Setup buildroot and prepare Buildroot build
make c3_docker-linux_buildroot_setup
make c3_docker-linux_buildroot_prepare
# Build Buildroot system (may take >1h)
make c3_docker-linux_buildroot_build
# Run Buildroot system with C3 enabled on Simics
make c3_docker-linux_buildroot_run
# The following command also combines all the steps:
make c3_docker-linux_buildroot
To boot up a C3-hardened EDK2 you will need to build EDK2 itself but also build a Buildroot filesystem to boot up into. The build targets automatically use Docker for most of the builds, and you can build and run with Make:
# Checkout EDK2 submodules and build EDK2 in Docker container
make edk2
# Build the Buildroot system in Docker container
make edk2_buildroot
# Run edk2 in Simics with C3 (with some default settings)
make edk2_run
Once built, you can also manually boot EDK2 and configure the system:
# Without C3 pointer encoding enable (i.e., no C3 protections)
./edk2_src/scripts/edk2_run_linux.sh run --disable_ptrenc
# With C3 and integrity enabled
./edk2_src/scripts/edk2_run_linux.sh run --integrity_enabled
# With networking on (e.g., to login via SSH)
./edk2_src/scripts/edk2_run_linux.sh run --net
# SSH into simulation with C3 EDK2 (from other shell)
make edk2-buildroot-ssh
All the build commands in this document are using a Docker container with necessary dependencies installed. For running Simics, you can then alternatively either use a host-installed Simics to run the workloads, or use the Simics instance installed in the Docker container.
In particular for debugging and using the Simics GUI, you may want to install Simics on your development machine. See Installing and running Simics on host for details on how to do that.
If you need to use proxies, you need to modify the proxy setting in the following locations:
-
In
scripts/docker/Dockerfile_base
, either before or after theapt
command; depending on local proxy configurations. -
In
scripts/install_ubuntu.simics
, you may need to configure a proxy for use during Ubuntu installation. After the$sercon.bp-wait-for-console-string "proxy information"
, add the the following line$sercon.input "http://<proxy-address:<proxy-port>"
just before the next$sercon.input "\n"
line.
To facilitate using running either on host or within Docker, the build and
output directories are bound from the host to the container. So building a
checkpoint in or outside Docker results in the same output on the host machine.
See scripts/make/docker.mk
for the full list of bound directories.
To manually work within Docker, e.g., to run Simics from the container, you can run:
make c3_docker_shell
Most makefile targets will automatically run within Docker, you can suppress
this behavior by adding NO_DOCKER=1
to the makefile run command. This is
typically implemented by internally prefixing the non-docker Makefile target
with c3_docker-
, which automatically spawns the Docker container and runs the
same make command without the c3_docker-
prefix. You can always use the
dry-run -n
flag to check the commands that would be run by make.
That is, the following three commands are equivalent:
# To automatically build checkpoint in Docker:
make cc_kernel
# , or:
make c3_docker-ckpt-cc_kernel
# or to manually, enter Docker:
make c3_docker_shell
docker> make ckpt-cc_kernel
Both commands will build update the checkpoints/cc_kerenl.ckpt
checkpoint on
your host machine and allow it to be used either from within Docker, or from the
host machine.
ℹ️
|
The Simics module builds are not persistent in the Docker container, so if you use the C3 Simics model, you will need to manually build it each time when entering the Docker shell. (Build targets that need the Simics model automatically do this for you.) |
# To clean only Simics modules:
make clean
# To clean most build artifacts (e.g., for glibc, llvm, and linux), run:
make mrproper
Neither of the commands will remove checkpoints. To do so, delete the
checkpoints
folder manually. Checkpoints are by default incremental
and depend on the originating checkpoint, so you want to avoid deleting old
checkpoint that may have latter dependent checkpoints still in use.
For frequent re-builds, the build system tries to optimize builds by caching intermediate artifacts and use CCache where possible. Specifically, the build system will use the following directories for caching:
${HOME}/.c3-buildroot-ccache
${HOME}/.c3-linux-ccache
${HOME}/.c3-llvm-ccache
The Buildroot systems will when available use a pre-built external toolchain to
avoid building the whole toolchain during setup. This is stored in
/opt/simics/buildroot_toolchains and defined in the
edk2_src_scripts/edk2_run_linux.sh
script and corresponding Buildroot
configuration file defined in edk2_src_scripts/edk2_run_linus.sh
.
You can find Simics documentation at https://simics-download.pdx.intel.com/simics-6/docs/html/.
To run Simics directly, you can use the following command:
./simics [simics_args] [run_arg1=val1 run_arg2=val2 ...]
Useful simics_args (optional):
--help |
View Simics usage and help. |
-no-win |
Run simics with GUI windows hidden (can be displayed on demand). |
-batch-mode |
Run in batch mode (will exit with 0 on success or non-zero on error). |
The Simics shell has support for <TAB> completion, command history, and has very
helpful help
and apropos
commands. In particular, the help command often
works for complex objects and commands (e.g.,
help board.mb.cpu.mem[0][0].examine-memory
).
Some common task you may need are:
# Run and stop simulation (also Ctrl-C)
run
stop
# Save or load "checkpoint"
write-configuration <path>
read-configuration <path>
# Setting breakpoints
help bp
# Disassemble code at address (RIP by default)
disassemble count=20
# Read register and memory values
read-reg rip
board.mb.cpu0.mem[0][0].examine-memory (read-reg rip)
ℹ️
|
The dependencies and installation instruction are tested for Ubuntu 20.04. For other systems you may have to adapt the instruction. |
Download and install Simics v.2024.25 from https://software.intel.com/content/www/us/en/develop/articles/simics-simulator.html.
Create an /opt/simics
directory owned by the current user.
The following commands can be executed in a directory where both the Simics package bundle and the package manager archive have been downloaded to install Simics:
tar xf intel-simics-package-manager-1.9.4-linux64.tar.gz
intel-simics-package-manager-1.9.4/ispm packages --install-bundle simics-6-packages-2024-25-linux64.ispm --install-dir /opt/simics/simics-6.0.198 --non-interactive
Next, launch the package manager GUI with intel-simics-package-manager-1.9.4/ispm-gui
to associate
the needed addons with the Simics base package using the following steps:
-
When asked for the installation path for packages, enter
/opt/simics/simics-6.0.198
and click "Save". -
Click the "Addons" tab.
-
Select "QSP-x86", "QSP-Clear-Linux", and "QSP-CPU".
-
Click "Save updates".
-
Close the package manager GUI.
If the addon tab is empty and you encountered a "Unable to load manifest" error during installation, you can navigate to the Platforms tab and manually import the corresponding manifest file from the installation path.
The Simics VMP kernel module significantly accelerate simulation. But as is, it may not be compatible with your system kernel or security requirements (e.g., module signing). If possible, it can be installed with:
/opt/simics/simics-6.0.198/bin/vmp-kernel-install
On Ubuntu 20.04, initial dependencies can be installed with:
apt install git curl make gcc
After cloning the C3 repository, you can then install the rest of the dependencies with:
# To directly run (using sudo)
make install_dependencies
# To view commands (e.g., to install manually):
make -n install_dependencies
Once Simics is installed, you configure simics for the current project with:
# To setup with Simics in /opt/simics/simics-6/simics-latest/bin
make simics_setup
# or set other SIMICS_BIN directory with
make simics_setup SIMICS_BIN=/some/other/path/bin
# Create a new cc_llvm checkpoint with:
make ckpt-cc_llvm
# Build Cryptographic Computing Simics modules
make -B
Most of the build commands for C3 Simics checkpoints, software, or other
artifacts will automatically use the C3 Docker container. However, if you
have necessary dependencies installed on your machines, you may be able to
also build the software without Docker, to do so, add the NO_DOCKER=1
option
to the corresponding Make command.
For instance:
# Using Docker, you can create a cc_llvm checkpoint with:
make cc_llvm
# To build without Docker, you can use any of:
make cc_llvm NO_DOCKER=1
make c3_docker-ckpt-cc_llvm NO_DOCKER=1
make ckpt-cc_llvm
ℹ️
|
Builds on the host are not supported or actively tested. They are likely to fail on many systems. Please use Docker builds for the most reliable results. |
The C3 functional model is implemented in Simics. It supports various different run-time arguments configurable via the Simics shell or scripts. The main attributes are:
enable_integrity |
Enable C3 integrity checking. |
break_on_exception |
Break on exceptions (excluding page faults). |
cc_context |
Access Access C3 configuration. |
debug |
Enable debug printouts for C3 operations. |
You can access these attributes via the Simics shell, e.g., to start debug mode you can do
# Read debugging flag
cc0_0->debug
# Enable debugging
cc0_0->debug = TRUE
# Disable debugging
cc0_0->debug = FALSE
You typically will not access these variables directly but rather use the scripts for user-space, Linux, or EDK2 to configure the model.
The main Simics model code is in the modules
folder, but the model also uses
code from the crypto
and malloc
folders. In particular the
malloc/cc_globals.h
header file is also used by other software artifacts (such
as the C3 Linux kernel, glibc, and LLVM).
|
Implementation for Ascon. |
|
Implementation for BipBip. |
|
Helper class for C3 pointer and data encoding in software. |
|
Shared definitions for various C3 functionality. |
|
Model-specific Simics implementation. |
|
Shared Simics classes and code. |
The following commands create doxygen documentation for malloc
, crypto
and
modules
under doc/doxygen
, you can browse the docs by starting from
doc/doxygen/html/index.html
. The documentation is auto-generated from inline
annotations in comments in the source code files themselves.
make documentation
To maintain code readability, we use clang-format and cpplint to enforce code style and formatting. Please install pre-commit hooks to verify code already on commit. To do so, run:
# To install, run:
make pre-commit-install
# To uninstall, run:
make pre-commit-uninstall
You will also need to install cpplint and clang-format on your development machine as those are used by pre-commit.
On commit, pre-commit will automatically run checks configured in
.pre-commit-config.yaml
. During the scan, it will only modified files that
have been staged such that you can afterwards inspect changes using git diff
.
You may need to address some issues manually, but simple formatting issues can
be automatically applied to all staged files using git clang-format
.
Alternatively, you can manually apply clang-format on the full file with
clang-format -i <filename>
.
A typical workflow is:
# Stage changes
git commit
# -> if no errors, commit goes through, otherwise:
# Inspect changes by pre-commit
git diff
# If okay, apply
git add
# Apply clang-format to changed files
git clang-format
# Inspect changes by clang-format
git diff
# If okay, apply
git add
git commit
# If needed, fix remaining issues manually
In some cases you may not be able to fix all changes, or you may need to commit
files that intentionally violate code style rules. To do so, you can run git
commit --no-verify
. However, when possible, avoid disregarding issues as we may
begin to enforce these rules on pull-requests.