This post explains how to enable UEFI SecureBoot on Debian, using your own trust chain. The
technical part itself is very light, most of the post is explanations and what and why.
What is SecureBoot ?
UEFI SecureBoot is a mechanism to verify a cryptographic signature of UEFI Images before loading
them into the Firmware (the new name for the BIOS1). This provides a way to control which
images are allowed, and also drivers and option ROM used by the Firmware, and to fight bootkits and
malwares based on that. For an example of such dangers, see my past presentations on malicious UEFI
Option ROMs ([FR] at SSTIC, and
[EN] at PacSec).
Roughly, SecureBoot will rely on cryptographic signatures (mainly using SHA-256 and RSA-2048) that
are embedded into files using the
Authenticode
file format. The integrity of the executable is verified by checking the hash, and the authenticity
and the trust by checking the signature, based on X.509 certificates, which has to be trusted by
the platform.
At a high level, the Firmware has 4 different set of objects (see figures for details):
the Platform Key (PK): this is the main key. This keys, usually belonging to …
Since the blog was migrated (in fact,
the entire server), I was wondering what to do with the previous content
(especially the redmine installation, and the public git).
I don’t like the idea of installing a new redmine server (and dynamic
content), so I’ve decided to throw away all the previous content and public only
the new, static, content. This also makes the installation easier, because the
LXC containing the web server is read-only :)
Some of the active projects are now published on github:
In the previous examples, we’ve seen how to build OCaml applications to read,
manipulate and write LLVM bitcode.
To be able to generate realistic code, we now need to add a few more things.
This part explains how to create bitcode with a correctly specified target
triple, how to verify bitcode, and write a hello world application.
Target Triple and Data Layout
While LLVMIR is (or should be) target independent, there are a few things that
are not. For example, the support for some instructions, the padding and
alignment inside structures, the endianness, the size of pointers, etc.
All these things are specified in two attributes of modules: the target triple,
and the data layout.
In the current (3.5) version of LLVM, these two attributes are optional.
However, they could become mandatory in the future, so it is best specifying them.
Note: in my personal opinion, specifying that inside the module is clearly
redundant with the -march= option of llc. Most of this could have been
handled by compiler flags, instead of creating situations where one can …
The previous articles explain how to build applications using the OCaml-LLVM
bindings, and how to use the API to manipulate the LLVM objects. This was the
“read-only” part of the tutorial, which can be used to analyze LLVMIR.
This part explains how to create LLVMIR, and write a simple application from
scratch, and see how to build and run it.
Modules
As in the previous tutorial, we need
to create a context and a module:
There are two actions that can be done on functions:
declare_function to give only a declaration of the prototype,
define_function to give both the declaration and the implementation.
In both cases, we need to give the signature (return type, number and type of
arguments) of the function.
This is pretty similar to C. We’ll use this to declare the function
int main(void).
The int type is a bit problematic in LLVM (and in C, but for other reasons):
integer types must have a known size in LLVM. While this does not change the
architecture-independent property …
In the previous tutorial, we’ve seen how to use ocamlbuild and make to build
a simple application. In this part, we’ll start exploring the API, and see how
to access values and attributes of LLVM objects.
The base of the code is the same as in part 1: it reads an existing LLVM bitcode
file, for example one generated by clang.
As in previous tutorial part, knowing the LLVM C++ API is not required (but can help).
LLVM objects
The top-level container is a module (llmodule). The module contains global
variables, types and functions, which in turn contains basic blocks, and basic blocks
contain instructions.
Values
In the OCaml bindings, all objects (variables, functions, instructions) are
instances of the opaque type llvalue.
A value has a type, a name, a definition, a list of users, and other things like
attributes (for ex. visibility or linkage options) or aliases.
Each value has a type (lltype), which is a composite object to define the type
of a value and its arguments. To match the real type, it needs to be converted
to a TypeKind.t:
This is the first part of a tutorial series, on how to use the OCaml bindings
for LLVM.
Why use OCaml bindings ? Because you can avoid using the C++ API, spending huge
amounts of time compiling Clang sources, then your plugin, then debugging the
segfaults again and again. The bindings are stable, cover most of the API, and
are quite simple to use, thanks to the Debian packages.
This tutorial is written based on a Debian Sid, things may differ but should
stay similar on other distributions.
The objectives of this first part are:
install the required packages
setup a build environment for ocamlbuild
build a simple application that reads an LLVM bitcode file and prints it
Installation
The required packages are:
llvm-3.5-dev
libllvm-3.5-ocaml-dev
the LLVM and OCaml compilers (llvm-3.5, ocaml)
optionally, clang
The current LLVM version is 3.6, however the OCaml bindings are currently
disabled (See Debian bug
#783919), because of
changes in the required dependencies.