Skip to content

C3-Simulator is a Simics-based functional simulator for the X86 C3 processor, including library and kernel support for pointer and data encryption, stack unwinding support for C++ exception handling, debugger enabling, and scripting for running tests.

License

Notifications You must be signed in to change notification settings

IntelLabs/c3-simulator

Repository files navigation

Cryptographic Capability Computing (C3) Simulator

⚠️

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.


Quick Start

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.

Quick-start: Setting up the C3 simulator

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

Optional: Running Simics on host

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]

Quick-start: C3 gem5-based performance simulator

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.

Quick-start: C3 protected user-space applications

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.

Quick-start: C3 protected Linux kernel

To build and run C3-hardened Linux kernel, run:

make c3_docker-linux_buildroot

See C3 protected Linux kernel for more details.

Quick-start: C3 protected EDK2

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.

C3 demos

Clang Tidy

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

Uninitialized Memory Read (CWE457) detection

C3 can be used to detect uninitialized memory reads, using integrity check values.

To run demo:

make c3_docker-demo-cwe457.sh

Stack unwinder hardening

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

LLDB demo

The C3 LLVM includes a C3-aware LLDB debugger, and the C3-kernel can furnish coredumps with additional metadata to facilitate debugging of C3-protected applications.

To view a demo of this, run:

make c3_docker-demo-lldb_debug_01

Tests and evaluations

Unit tests

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 --model to run all on all default models, but still exclude specific models.

-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

Testing different configurations

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

Adding new unit tests

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.

Juliet

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.

C3 protected user-space applications

Setting up C3 user-space environments

We provide multiple different environments / checkpoints to test different aspects of C3. The main environments and build commands are:

Checkpoint Build command Description

checkpoints/cc_glibc.ckpt

make cc_glibc

C3 glibc, using system call shims.

checkpoints/cc_llvm.ckpt

make cc_llvm

C3 glibc and LLVM, using system call shims.

checkpoints/cc_kernel.ckpt

make cc_kernel

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.

Running workloads

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
Table 1. Common parameters for 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 /home/simics/llvm/llvm_install/bin/[clang|clang++] (Default: g++)

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

C3 integrity and intra-object tripwires

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.

Fine-grained control of integrity

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();

C3 user-space environment and configuration (optional)

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.

Shimmed checkpoints

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

Checkpoints with C3-aware kernel

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

Create initial Ubuntu checkpoint

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.
Manually building initial Ubuntu checkpoint (optional)

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).

Building LLDB with C3-coredump support

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).

C3 protected Linux kernel

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

C3 protected EDK2

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

C3 development environment

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.

Proxy configuration

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 the apt 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.

Working with Docker

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.)

Cleaning build artifacts and files

# 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.

Optimizing builds

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.

General notes on Simics

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)

Working without Docker

Installing and running Simics on host

Installing Simics on host
ℹ️
The dependencies and installation instruction are tested for Ubuntu 20.04. For other systems you may have to adapt the instruction.

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:

  1. When asked for the installation path for packages, enter /opt/simics/simics-6.0.198 and click "Save".

  2. Click the "Addons" tab.

  3. Select "QSP-x86", "QSP-Clear-Linux", and "QSP-CPU".

  4. Click "Save updates".

  5. 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.

(optional) Install VMP kernel module

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
Install other dependencies

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
Install updated cmake

To build the LLVM target, the may require a cmake version is newer than that provided by Ubuntu 20.04. To build locally, use:

make install-cmake

Setting up the C3 Simics environment on host

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

Building C3 environments without Docker

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.

C3 Simics simulation model

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.

Simics C3 model source code

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).

crypto/ascon.*

Implementation for Ascon.

crypto/bipbip.*

Implementation for BipBip.

crypto/sw_encoder.*

Helper class for C3 pointer and data encoding in software.

malloc/cc_globals.h

Shared definitions for various C3 functionality.

modules/<model>

Model-specific Simics implementation.

modules/commmon/ccsimics

Shared Simics classes and code.

Building Doxygen documentation

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

Contributing to the C3-simulator

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.

About

C3-Simulator is a Simics-based functional simulator for the X86 C3 processor, including library and kernel support for pointer and data encryption, stack unwinding support for C++ exception handling, debugger enabling, and scripting for running tests.

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published