\chapter{Implementation} \label{cha:implementation} The concept described in \autoref{cha:concept} will be implemented as a prototype to demonstrate a working implementation and to analyze the speed of those parts of a transaction. Although the goal is to put all these features on a highly integrated system, we decided to start with widely available hardware based on Intel's x86 architecture. \begin{figure} \centering \includegraphics[width=0.6\textwidth]{../resources/networkview3} \caption[Prototype schematic]{Prototype setup to show DAA features and the dataflow from BS to PIA} \label{fig:prototype} \end{figure} \autoref{fig:prototype} shows the setup on a connection level. To show the features of DAA, it is necessary to have three independent systems which are connected via a TCP/IP network. Every host is connected via ethernet to the other systems. To keep the setup minimal, the IP addresses are static and internet is only required during installation. Hence, Service Discovery is done statically, every host knows the IP addresses and functions of each other directly. \section{Hardware Setup} For demonstrating remote attestation via DAA over a simple network infrastructure, we use three systems with similar configuration. \autoref{tab:systems} shows the specification of these systems. We decided to order one system with an AMD processor in it to find differences in handling the TPM between Intel and AMD systems. All features used in this thesis were available on both platform types, so there were no differences found. \begin{table} \renewcommand{\arraystretch}{1.2} \centering \caption{Systems used for demonstration prototype} \label{tab:systems} %\rowcolors{2}{lightgray}{white} \begin{tabular}{rp{3.6cm}p{3.7cm}p{3.7cm}} \toprule &\textit{System 1}&\textit{System 2}&\textit{System 3} \\ \midrule \textbf{Processor} &AMD Athlon 240GE &Intel Pentium G4560T &Intel Pentium G5400T\\ \textbf{Mainboard} &Gigabyte B450I Aorus Pro Wifi &Gigybyte GA H110N &Gigabyte GA H310N\\ \textbf{Memory} &8GB DDR4 &8GB DDR4 &8GB DDR4\\ \textbf{Storage} &NVMe SSD 128GB &NVMe SSD 128GB &NVMe SSD 128GB \\ \textbf{TPM module} &Gigabyte TPM2.0\_S &Gigabyte TPM2.0 &Gigabyte TPM2.0\_S \\ \textbf{TPM chip} &Infineon SLB9665TT2.0 &Infineon SLB9665TT2.0 &Infineon SLB9665TT2.0 \\ \bottomrule \end{tabular} \end{table} The used mainboards come with a dedicated TPM~2.0 header which may differ from board to board. A 19-pin header is available on the older platform of \emph{System 2}. As long as TPM and mainboard have the same 19-pin connector they will be compatible to each other. The newer Gigabyte mainboards come with a proprietary 11-pin connector which is only compatible with Gigabyte's TPM2.0\_S module. All modules are however electrical compatible since only unused pins of the full size connector are removed. With a wiring adapter any TPM board would work on any mainboard supporting TPM~2.0 even when coming with a proprietary header. \section{Select the Operating System} The OS needs to fulfill three requirements for this prototype. First, the TPM must be supported by the kernel. Second, the OS has to support a recent version of the TPM software stack (TSS 3.0.x or newer at the point of writing) for using the Xaptum ECDAA~\cite{xaptum21} project with enabled hardware TPM. Similarly, the \texttt{tpm2-tools} must be available in a version newer than \texttt{4.0.0}. Finally, the support for the Integrity Measurement Architecture (IMA) must be activated in the kernel and supported by the OS. This feature is available in the mainline Linux kernel. However, the corresponding kernel compile parameters must be set. Ubuntu 20.04 LTS does fulfill above mentioned requirements by default. Ubuntu is also supported by the Xaptum ECDAA project, although compatibility was tested with an older OS version (18.04). When installing Ubuntu on the prototype, we used \emph{Full Disk Encryption} (FDE) which leads to the disk allocation described in \autoref{tab:disklayout}. Ubuntu installs Grub by default, which we will use in the following as a fallback bootloader. \begin{table} \centering \begin{tabular}{llll} \toprule \emph{Partition} &\emph{Size} &\emph{Mountpoint} &\emph{Comment}\\ \midrule \texttt{nvme0n1p1} &512M &\texttt{/boot/efi} &EFI boot partition\\ \texttt{nvme0n1p2} &1G &\texttt{/boot} &Bootloader partition (Grub)\\ \texttt{nvme0n1p3} &118G & &lvm on dm\_crypt\\ \texttt{ubuntu--vg-ubuntu--lv} &118G &\texttt{/} &root partition on lvm\\ \bottomrule \end{tabular} \caption{Disk layout of the BS prototype} \label{tab:disklayout} \end{table} %In the next section we describe the basic setup of the OS to prepare Trusted Boot. %The DAA implementation of Xaptum\footnote{\url{https://github.com/xaptum/ecdaa}} supports Debian Linux and Ubuntu as operating system when interacting with a hardware TPM. %At the time of writinng, the most recent version of Ubuntu 20.04 LTS supports the TPM2.0 as well as the Xaptum DAA library and the Integrity features which are integrated in the Kernel \section{Trusted Boot} Parts of this section contain results of the master project which documented how to build an Linux environment with TPM backed full disk encryption. This includes the evaluation which Linux distributions support trusted boot, the scripts to handle the encryption key in the TPM and the documentation how to build the unified kernel. By default, every mainboard with support for TPM~2.0 must support trusted boot. When a TPM becomes available, the UEFI/BIOS itself takes all required measures until the boot process is handed over to the OS bootloader (e.g. Grub). Since Ubuntu uses GRUB 2.04 as bootloader which has TPM support by default, trusted boot needs just to be enabled in the Grub configuration. In this case, Grub will be measured from the BIOS to the PCRs 4 and 5, as shown in \autoref{tab:PCR}. According to the documentation~\cite{grub19}, Grub itself uses PCR 8 for executed commands, the kernel command line and all commands forwarded to kernel modules. PCR 9 is used to measure all files read by Grub. Embedded systems like a rolled out version of the BS do not need several boot options, making Grub unnecessary. Therefore we can replace Grub's bootloader EFI file with a blob containing all required information to load the kernel directly. This kernel decrypts the disk and boots the remaining system autonomously. Pornkitprasam~\cite{pornkitprasan19-diskencryption} \cite{pornkitprasan19-tpmtools} and the Tevora company~\cite{tevora-secureboot} introduced the concept of a \emph{Unified Kernel} for Ubuntu and Arch respectively. This large EFI file contains the initramfs, kernel command line and the kernel itself. \autoref{tab:efilayout} shows the content of the EFI blob with the corresponding offset addresses as well as the sources in the file system. \begin{table} \centering \begin{footnotesize} \begin{tabular}{lll} \toprule \emph{Address} &\emph{Source path} &\emph{Comment}\\ \midrule \texttt{0x0000000} &\texttt{/usr/lib/systemd/boot/efi/linuxx64.efi.stub} &Linux EFI Stub\\ \texttt{0x0020000} &\texttt{/usr/lib/os-release} &Linux OS release information\\ \texttt{0x0030000} &\texttt{/boot/kernel-command-line.txt} &Kernel command line parameters\\ \texttt{0x0040000} &\texttt{/boot/vmlinuz} &latest kernel image\\ \texttt{0x3000000} &\texttt{/boot/initrd} &latest initial ramdisk\\ \bottomrule \end{tabular} \end{footnotesize} \caption{Memory layout of the Unified Kernel EFI file} \label{tab:efilayout} \end{table} All binary resources are available as blobs which can be imported directly. Only the command line parameters need to be customized. \subsection{Install and use Trusted Boot} \label{ssec:install-and-use-trusted-boot} The following shell scripts are available online\footnote{\url{https://git.ins.jku.at/proj/digidow/trustedboot}}. All are tested on a Ubuntu 20.04 server minimal installation on all three devices. These packages need to be installed beforehand to make use of the scripts: \begin{itemize} \item \texttt{binutils} for objcopy, generating the unified kernel, and \item \texttt{tpm2-tools} to interact with the onboard TPM, \end{itemize} Installing trusted boot is done in three steps, assuming being root on the target system: \begin{enumerate} \item \emph{Execute \texttt{install.sh}}: It installs the shell scripts into \texttt{/usr/sbin} and adds a new random passphrase to LUKS. It furthermore adds TPM support to the initramfs and creates the unified kernel described above. \item \emph{Reboot}: During reboot, the new PCR values are generated. \item \emph{Execute \texttt{update-luks-tpm.sh}}: The new PCR values are used to seal the LUKS passphrase into the TPM. \end{enumerate} After finishing these steps, the system should be able to decrypt the FDE without user interaction and end up at the login prompt. The automatic boot will now work as long as there are no updates affecting the unified kernel. If a kernel update happens during upgrading the system, a new EFI blob must be generated and the TPM seal is to be renewed. Similar to the installation procedure, this can be done in the following procedure: \begin{enumerate} \item \emph{Execute \texttt{update-kernel.sh}}: This includes the latest updates of kernel, its parameters and the initramfs into the EFI blob. \item \emph{Reboot}: Again, the new PCR values need to be calculated. \item \emph{Execute \texttt{update-luks-tpm.sh}}: Similar to the installation, the new seal is generated and replaces the old one. \end{enumerate} The result is a recent kernel with up-to-date configuration. \subsection{Detailed description of the scripts} \autoref{code:tbcommandlinetxt} shows the used command line which will be saved on \texttt{/boot/kernel-command-line.txt}. \lstinputlisting[float,caption={\texttt{kernel-command-line.txt}: Command line for the Kernel}, label={code:tbcommandlinetxt}]{../../trustedboot/kernel-command-line.txt} Relevant for trusted boot is the parameter where the root file system is located. This example works for the default Ubuntu LVM on LUKS configuration. The parameters activate also IMA which will be discussed later in this chapter. If FDE is installed, the boot process needs to be aware of how to decrypt the disk. Therefore, the initramfs needs the LUKS binaries as well as the TPM software stack to unseal the passphrase with the PCR registers. The unseal operation itself is then done with \autoref{code:tbpassphrasesh}, which also needs to exist in the initramfs. \lstinputlisting[float,language=bash, caption={\texttt{passphrase-from-tpm.sh}: Initramfs-script to ask the TPM for the LUKS key}, label={code:tbpassphrasesh}]{../../trustedboot/passphrase-from-tpm.sh} We copy the script of \autoref{code:tbtpm2hooksh} to \texttt{/etc/initramfs-tools/hooks} to enable TPM access during boot after the next initramfs update. \lstinputlisting[float,language=bash, caption={\texttt{tpm2-hook.sh}: Script copying required TSS files into the initramfs}, label={code:tbtpm2hooksh}]{../../trustedboot/tpm2-hook.sh} Next, the script of \autoref{code:tbcreatelukssh} creates a new key for FDE by using the random number generator of the TPM. It is saved in clear text in \texttt{/root/keys} to be able to update the sealing operation when new PCR values are used. Using a clear text password file in the \texttt{/root} directory is not per se considered insecure as the disk must be decrypted beforehand, meaning that the passphrase also exists unencrypted in memory. Furthermore only root has access to the target directory. The backup is needed for updating the system and when issues with the TPM appear. When an updated kernel is booted, the seal cannot be opened anymore since the old PCR values cannot be restored anymore. It is, of course possible to generate a new passphrase every time when the PCR values change by intention. In this case no passphrase need to be stored on the file system. Finally, \autoref{code:tbupdatekernelsh} creates the unified kernel according to \autoref{tab:efilayout} using the command \texttt{objcopy} and copies it on the EFI disk partition. The offset addresses need to be chosen according to the size of the included blobs. All steps described above are summarized in \autoref{code:tbinstallsh}. \lstinputlisting[float,language=bash, caption={\texttt{update-kernel.sh}: Script for updating the unified Kernel}, label={code:tbupdatekernelsh}]{../../trustedboot/update-kernel.sh} \lstinputlisting[float,language=bash, caption={\texttt{create-luks-tpm.sh}: Script to create a new LUKS key}, label={code:tbcreatelukssh}]{../../trustedboot/create-luks-tpm.sh} \lstinputlisting[float,language=bash, caption={\texttt{install.sh}: Script to install Trusted Boot on Ubuntu}, label={code:tbinstallsh}]{../../trustedboot/install.sh} When the unified kernel is installed, the system needs to be rebooted to generate the PCR values for the new boot chain. The FDE decryption with the TPM will of course fail, since there is no sealed passphrase available yet. This step is done now since the new unified kernel is measured the first time. \autoref{code:tbupdatetpmsh} shows how the passphrase is sealed into the TPM with all relevant PCR registers. \lstinputlisting[float,language=bash, caption={\texttt{update-luks-tpm.sh}: Script for updating the Sealing of the TPM Object with new PCR values},label={code:tbupdatetpmsh}]{../../trustedboot/update-luks-tpm.sh} Line 15 of the script shows the unseal operation which is used to get the passphrase out of the TPM. It should result in an exact copy of the original passphrase in \texttt{/root/keys}. This finishes the installation of trusted boot resulting in an unattended disk decryption process during system boot. The result is a trusted boot chain which ensures, that the system only has access to the encrypted disk when the kernel with its parameter is known---and therefore trusted. \section{Integrity Measurement Architecture} The result of trusted boot is a measured and therefore trusted kernel with its command line parameters and modules. IMA extends this trust to the file system as described in \autoref{sec:integrity_measurement_architecture}. All features of IMA are already implemented in the kernel sources and do not need additional packages. The Gentoo wiki page about IMA~\cite{gentoo19} describes which kernel compiler flags are required to enable IMA in a Gentoo kernel. According to their blog~\cite{RedHat2020}, Redhat supports IMA since Enterprise Linux 8 and so would the Redhat clones like CentOS, Rocky or Alma Linux. Ubuntu enabled the required kernel compile flags by default on version 20.04 in the Ubuntu kernel repository\footnote{\url{https://kernel.ubuntu.com/git/kernel-ppa/mirror/ubuntu-5.4-focal.git/tree/security/integrity/ima/Kconfig}, last visited on 9.7.2021}. However, we found no official information on when IMA was introduced or whether IMA support will continue in future releases. Every kernel supporting IMA creates a virtual file at \texttt{/sys/kernel/security/ima/ ascii\_runtime\_measurements}. When IMA is disabled, which is the default, this file has only one entry representing the boot aggregate. By enabling IMA via kernel command line parameters, this virtual file gets filled according to the policies defined. The first four parameters used in the kernel command line as shown in \autoref{code:tbcommandlinetxt} define the behavior of IMA and how the measurement log should look like. \begin{itemize} \item \texttt{ima\_appraise=fix} appends the filehash as an extended file attribute for every accessed file. \item \texttt{ima\_policy=appraise\_tcb} together with \texttt{ima\_policy=tcb} analyze files owned by root and opened for execution. \item \texttt{ima\_hash=sha256} sets the hashing algorithm. \item \texttt{rootflags=i\_version} must be enabled when mounting the file system since IMA is checking the \texttt{i\_version} number before re-hashing the resource. When it is disabled, the kernel has to hash the resource every time. \end{itemize} Unfortunately, the resulting integrity log is between 2000 and 3000 lines long when the system is freshly booted. The log can blow up to several 10000 lines when the up time exceeds several days. Therefore, IMA has a policy language where rules for hashing files can be customized. It might, for example, be useful to exclude log files from being hashed. A third party can comprehend the state of the attesting system, when parsing the integrity log. Together with the corresponding value of PCR 10, where the hashes of all entries are chained, the TPM can \texttt{certify} correctness of the log. Besides the log entries, every hashed file gets an extended file attribute called \texttt{security.ima} which holds the current hash value in base64 encoding. The apt package \texttt{attr} contains the binary \texttt{getfattr} which can show these additional attributes with the following command: \begin{lstlisting}[numbers=none] getfattr -m - -d trustedboot/install.sh \end{lstlisting} Having attributes for all relevant files allows IMA to enforce appraisal. This means that the hash of every file is checked before accessing the file. Before enforcing IMA, the root file system should be parsed to create attributes for every file. Touching the file is not enough, the file must be opened for read. The following command opens every file in an ext4 file system for read, causing the kernel to create/update the file attributes, but does not read any data: \begin{lstlisting}[numbers=none] time find / -fstype ext4 -type f -uid 0 -exec dd if='{}' of=/dev/null count=0 status=none \; \end{lstlisting} It takes about fifteen minutes to parse the file system on a Ubuntu minimal server system given the hardware described above. The final step is to enforce IMA appraisal via kernel command line parameter. By changing the parameter \texttt{ima\_appraise=enforce} in \texttt{/boot/kernel-command-line.txt}, IMA enforces the hash and will deny access if the hash is not correct. The new parameters are activated by using the workflow for updating the kernel described in \autoref{ssec:install-and-use-trusted-boot}. The result is a system which allows only resources with correct hash attribute to be read or executed. However, an adversary may still create the file hash itself and overwrite the file with the hash. Hence these hash values must be verified in some way before they can be trusted. Two options are therefore available: \begin{itemize} \item \emph{Attest}: Let the complete integrity log be part of remote attestation and verify the hash values against a trusted known value database. This makes the verification part very complex but the state of the attesting system is well documented. \item \emph{Sign}: Sign hash values for static files like executables or libraries. The host can directly check whether the file was tampered with and act accordingly. Linux kernels support this feature with the \emph{extended verification module} (EVM). \end{itemize} We use the variant where the integrity log is part of the message. Details about the message design will be discussed in \autoref{ssec:daa-network-protocol}. This variant makes the BS prototype implementation easier, however, it increases complexity to completely verify the message. It might be useful in the future to use EVM to prevent executing unsigned or modified code. \section{Runtime Analysis} IMA is a comprehensive tool for checking the integrity of a file or executable or library before it gets executed. When access is granted, IMA's job is done. Hence, IMA is a tool for static system analysis. An executable can however change its behavior during runtime, either intended with remote procedure calls or unintended with a remote code execution vulnerability. These attack vectors can be addressed with runtime analysis. One approach for runtime analysis is to create a log of syscalls for a certain process. Syscalls are the only interface from the program to the OS when managing resources needed by the program. Hence logging the trace of syscalls shows which resources it needs and which files are accessed or modified. Any unusual behavior could be detected immediately given a good knowledge of the used resources when executing a good version of the program. The trace logs are created with \texttt{auditd} which requires the corresponding apt package to be installed. \section{Prove TPM~2.0 Certificate Chain} Every TPM has a corresponding certificate which is part of a certificate chain maintained by the TPM manufacturer. In our case, Infineon certifies its TPM with a number of intermediate CAs which itself are certified with Infineon's root CA. The TPM certificate is available for RSA and ECC cryptofamilies respectively. Since the verification workflow is the same on all machines and for both cryptofamilies, we demonstrate on system 1 how the process works. Note that this works for Infineon TPMs. Other vendors like STM, AMD or Intel may provide certificates via download on their website. \begin{enumerate} \item Read the certificate from the TPM NVRAM. The RSA certificate is located at address \texttt{0x1c00002}, that for ECC on address \texttt{0x1c0000a}: \begin{lstlisting}[numbers=none] root@amd1:~# tpm2_nvread -C o 0x1c0000a -o amd1_ecc.crt \end{lstlisting} \item Download the certificates from the intermediate and root CA from Infineon's website: \begin{lstlisting}[numbers=none] root@amd1:~# wget https://www.infineon.com/dgdl/Infineon-TPM_ECC_Root_CA-C-v01_00-EN.cer?fileId=5546d46253f65057015404843f751cdc -O infineon_ecc_root_ca.crt #Infineon root CA root@amd1:~# wget https://www.infineon.com/dgdl/Infineon-OPTIGA-ECC-Manufacturing-CA_036-Issued_by_RootCA.crt-C-v01_00-EN.crt?fileId=5546d46262475fbe0162486417b73cbe -O infineon_ecc_intermediate_ca_036.crt #Infineon intermediate CA \end{lstlisting} \item Convert all certificates into PEM format. OpenSSL can only verify a chain in PEM format. \begin{lstlisting}[numbers=none] root@amd1:~# openssl x509 -inform DER -outform PEM -in infineon_ecc_root_ca.crt -out infineon_ecc_root_ca.pem root@amd1:~# openssl x509 -inform DER -outform PEM -in infineon_ecc_intermediate_ca_036.crt -out infineon_ecc_intermediate_ca_036.pem root@amd1:~# openssl x509 -inform DER -outform PEM -in amd1_ecc.crt -out amd1_ecc.pem \end{lstlisting} \item Check the certificate chain with OpenSSL. The root certificate and the intermediate certificate need to be concatenated into one file to allow OpenSSL to check the certificate chain as well. % \begin{lstlisting}[numbers=none] % root@amd1:~# openssl verify -verbose -CAfile infineon_ecc_root_ca.pem -untrusted infineon_ecc_intermediate_ca_036.pem amd1_ecc.pem % amd1_ecc.pem: OK % \end{lstlisting} \begin{lstlisting}[numbers=none] root@amd1:~# openssl verify -verbose -CAfile <(cat infineon_ecc_intermediate_ca_036.pem infineon_ecc_root_ca.pem) amd1_ecc.pem amd1_ecc.pem: OK \end{lstlisting} \end{enumerate} When OpenSSL returns \texttt{OK}, the certificate chain is intact and the TPM is indeed one from Infineon. To be exact: The website, probably hosted by Infineon, provides a certificate chain which matches and the links to the corresponding parent certificate are correct. Unfortunately, Infineon does neither provide any website certification nor any checksums of the provided certificates. So, if the above described check fails, no source of trust can ensure that the root certificate is correct. We found that both, ECC and RSA chains of all TPMs are intact. For documentation reasons, we provide the OpenSSL SHA256 checksums of all used certificates in \autoref{tab:certchksum} of the Appendix. These checksums were generated with: \begin{lstlisting}[numbers=none] openssl x509 -noout -fingerprint -sha256 -inform pem -in amd1_ecc.pem \end{lstlisting} \section{Using the DAA Protocol} Direct anonymous attestation uses the TPM as cryptoprocessor and key store. The feature of identifiable instances of sensors is not required when interacting with the Digidow network. Only the \emph{trusted} state of the sensor system and the membership in the corresponding group is relevant. Hence, the group membership is an essential part to provide trust to the users, requiring a deep knowledge on what hardware and software is installed and which vulnerabilities it might have. The DAA group membership states that the system is provisioned from a trusted party, namely the DAA issuer. The level of trust is ultimate since the used version of DAA is only partly dynamic by lacking support of membership removal. During a Digidow transaction, the sensor attests its state by signing a message containing the integrity log and the PCR registers. Any party interacting with the sensor is then able to check trustworthiness via integrity and valid membership of the sensor. We describe in the following which programs need to be installed and what configuration is required to demonstrate a working implementation of DAA. \subsection{Provision Hosts of Test Setup} The demonstration setup, shown in \autoref{fig:prototype}, consists of three independent hosts which are connected together via TCP/IP. Every host represents one party in the DAA scheme, each requiring additional software to support the DAA protocol. Xaptums ECDAA library needs to be installed on all three hosts but only the sensor requires TPM support. Similar to that, the ECDAA network wrapper is required to support the network communication part. The member needs, besides DAA protocol support, software to capture and process an image of the USB webcam. We developed a small Rust program called \texttt{bs-capture} for capturing a face image from a webcam. For biometric processing, we transform the image into an embedding with the face recognition prototype of Digidow\footnote{\url{https://git.ins.jku.at/proj/digidow/prototype-facerecognition}}. \subsection{Installing Xaptum ECDAA Library} Xaptum's ECDAA library provides the cryptographic functions and the protocol primitives for DAA. A file based demonstration of the protocol is provided within the project. We have to build the ECDAA library from source since the provided deb packages do not officially support Ubuntu 20.04. Therefore we need the C build environment as follows: \begin{lstlisting}[numbers=none] root@amd1:~# apt install gcc cmake build-essential doxygen doxygen-latex parallel \end{lstlisting} The sensor host requires TPM support which is enabled with the additional package \texttt{libtss2-dev}: \begin{lstlisting}[numbers=none] root@amd1:~/ecdaa/build# apt install libtss2-dev \end{lstlisting} Download the repository from GitHub\footnote{\url{https://github.com/xaptum/ecdaa}} and create the build folder on the file system: \begin{lstlisting}[numbers=none] root@amd1:~# git clone https://github.com/xaptum/ecdaa.git root@amd1:~# mkdir -p ecdaa/build && cd ecdaa/build \end{lstlisting} The next step is to build and install the required dependencies from source. Cmake uses the environment variable \texttt{CMAKE\_PREFIX\_PATH} as installation target. Xaptum provided a shell script for the complete routine: \begin{lstlisting}[numbers=none] root@amd1:~/ecdaa/build# export CMAKE_PREFIX_PATH=/usr root@amd1:~/ecdaa/build# ../.travis/install-amcl.sh ./amcl /usr FP256BN \end{lstlisting} Finally install the build of the project with \texttt{cmake}. Set the variable \texttt{DECDAA\_TPM\_SUPPORT} respectively: \begin{lstlisting}[numbers=none] root@amd1:~/ecdaa/build# cmake .. -DCMAKE_BUILD_TYPE=Release -DECDAA_CURVES=FP256BN -DCMAKE_INSTALL_PREFIX=/usr -DECDAA_TPM_SUPPORT=ON root@amd1:~/ecdaa/build# cmake --build . --target install \end{lstlisting} Now, all prerequisites are installed to build and install the ECDAA network wrapper which is a contribution of this thesis. \subsection{DAA Network Protocol} \label{ssec:daa-network-protocol} The network protocol provided by \texttt{ecdaa-network-wrapper} adds a network communication layer to the cryptographic implementation of Xaptum's ECDAA project. It is designed to match the workflow of a Digidow transaction, affecting the decision which party is defined as listener and which as sender. \begin{itemize} \item \emph{Start DAA issuer listener}: During startup of the issuer server, the program loads the public/private key pair if present. Otherwise, a new key pair will be created. The DAA issuer listener is always active to manage group subscriptions and queries for the group public key. \item \emph{Broadcast DAA group public key}: The group public key created by the DAA issuer is necessary for group enrollment and for verification of any messages signed by a DAA group member. Consequently, DAA verifier and (potential) DAA member must get this key first. \autoref{fig:daa-network-publish} shows the two steps that are visible on the network. Since this communication contains only public data, no additional privacy measurements are required. \begin{figure} \centering \includegraphics[width=0.6\textwidth]{../resources/daa-network-publish} \caption{Protocol to get the DAA issuer's public key} \label{fig:daa-network-publish} \end{figure} \item \emph{Enroll member to issuer's DAA group}: This step extends the DAA group and transfers the trust of the DAA group to the new member. This protocol requires the group public key to be present at the DAA member. If this is not the case, the member asks for it automatically. The procedure is a four-way handshake, as shown in \autoref{fig:daa-network-join}. We describe in \autoref{ssec:daa-protocol-on-lrsw-assumption} that the key exchange is cryptographically secure, meaning that no adversary can extract any private keys when getting access to these messages. When the member is eventually part of the DAA group, it is \emph{trusted} by the Issuer, requiring a thorough inspection of the member beforehand. Since we only show a working demo of the cryptographic concept, we skipped any efforts to check the member system in this implementation. \begin{figure} \centering \includegraphics[width=0.6\textwidth]{../resources/daa-network-join} \caption{Protocol to add a new member to the issuer's DAA group} \label{fig:daa-network-join} \end{figure} \item \emph{Send signed messages}: The diagram in \autoref{fig:daa-network-attest} shows that the DAA verifier listens and the member initiates the connection. \begin{figure} \centering \includegraphics[width=0.6\textwidth]{../resources/daa-network-attest} \caption{Protocol to send an attestation message to the DAA verifier} \label{fig:daa-network-attest} \end{figure} This implementation reflects the Digidow transaction workflow in mind where the sensor (=member) sends a signed message to the PIA (=DAA verifier). Hence, sending attestation messages with biometric information of the user will happen once per transaction in the Digidow network. \end{itemize} The message contains, as shown in \autoref{code:daamessageformat} the face embedding and the attestation information about the sending host. \begin{lstlisting}[float, caption={DAA message file format},label={code:daamessageformat}] embedding: sha1: sha256: imachecksum: ima_lines: \end{lstlisting} Instead of putting the plain integrity log into this message, we decided to use only checksum and the number of entries to keep the message size rather small. We continue this discussion in more detail in the next chapter. Furthermore, the the ECDAA library limits the message size for signing to 1024 Bytes. Thus, we created a SHA512 sum of the message and signed only this hash allowing us to send messages of arbitrary size and constant effort for signing. \subsection{Installing the DAA Network Protocol} The Network Wrapper can be downloaded from the Git repository\footnote{\url{https://git.ins.jku.at/proj/digidow/ecdaa-network-wrapper}}. Copy the folder \texttt{ecdaa-network-wrapper} to the build directory and change to this directory: \begin{lstlisting}[numbers=none] root@amd1:~# git clone https://git.ins.jku.at/proj/digidow/ecdaa-network-wrapper.git root@amd1:~# cd ecdaa-network-wrapper \end{lstlisting} Initialize Cmake with the following command: \begin{lstlisting}[numbers=none] root@amd1:~/ecdaa-network-wrapper# cmake . \end{lstlisting} Then build the preferred targets, depending which host is used. For example, to build the member binary with TPM support, use: \begin{lstlisting}[numbers=none] root@amd1:~/ecdaa-network-wrapper# cmake --build . --target ecdaa_member_tpm -- -j 2 \end{lstlisting} The following targets are available: \begin{itemize} \item \texttt{ecdaa\_issuer}: Creates the binary for the DAA issuer. \item \texttt{ecdaa\_member}: Builds the DAA member executable without TPM support. This should only be used for testing purposes. \item \texttt{ecdaa\_member\_tpm}: The DAA member binary with TPM support. \item \texttt{ecdaa\_verifier}: Creates the DAA verifier binary. \item \texttt{ecdaa\_all}: Builds every binary listed above at once. \end{itemize} When all above steps are finished successfully, the host is capable of taking its role in the DAA protocol. \section{DAA Demo Application} For demonstration purposes, we use an USB webcam to take a photo of the person being in front of the sensor. This photo is then processed to generate a face embedding, which is small enough to be sent with the DAA attestation message. The first part is done with a small Rust program called \texttt{bs-capture}, which is available online\footnote{\url{https://git.ins.jku.at/proj/digidow/bs-capture}}. It uses the libraries from the video4linux project to capture a still image and save it to disk. Ubuntu 20.04 requires the following packages to be installed: \begin{lstlisting}[numbers=none] root@amd1:~# apt install rustc cargo libv4l-0 libv4l-dev \end{lstlisting} Then the program can be downloaded and executed: \begin{lstlisting} root@amd1:~# git clone https://git.ins.jku.at/proj/digidow/bs-capture.git root@amd1:~# cd bs-capture/ root@amd1:~/bs-capture# cargo run \end{lstlisting} Cargo creates a binary in \texttt{target/debug/bs-capture} which can then be used for this prototype. The program assumes that a webcam is available at \texttt{/dev/video0}. It takes a still image which is saved as \texttt{frame.jpg} in the working directory, in this example \texttt{\textasciitilde/bs-capture}. This image needs to be processed to generate the face embedding data. Therefore we use the project \emph{Prototype Facerecognition} which uses a trained TensorFlow network to generate embeddings. The branch \texttt{retinaface-tflite} of the Git repository\footnote{\url{https://git.ins.jku.at/proj/digidow/prototype-facerecognition}} contains an install script which takes care of installing all dependencies for setup: \begin{lstlisting} root@amd1:~# git clone https://git.ins.jku.at/proj/digidow/prototype-facerecognition.git root@amd1:~# cd prototype-facerecognition/ root@amd1:~/prototype-facerecognition# git checkout origin/retinaface-tflite root@amd1:~/prototype-facerecognition# ./install.sh \end{lstlisting} This branch contains a TensorFlow version which was compiled to work on our test systems. The default version uses an instruction set extension which is not available on the Pentium Gold processors of System 2 and 3. When all parts are installed on the sensor, and issuer and verifier are ready to take connections from the sensor, the setup is finished. All tests of the following chapter are performed using above installation description.