├── .github └── workflows │ └── book.yml ├── .gitignore ├── LICENSE ├── README.md ├── alpine ├── Dockerfile ├── README.md ├── open-source-tpm-alpine-spdx.rdf └── tpmStartup.sh ├── book.toml ├── docs ├── Crim2022Tutorial │ ├── README.md │ └── tutorial.tex ├── Crim2023Tutorial │ ├── booted.png │ ├── gitdownload.png │ ├── profilesetup.png │ ├── rebootnow.png │ ├── selectiso.png │ ├── sshserver.png │ ├── success.png │ ├── tutorial2023.aux │ ├── tutorial2023.log │ ├── tutorial2023.pdf │ ├── tutorial2023.tex │ └── tutorial2023.toc ├── STARTHERE.md ├── SUMMARY.md ├── assets │ ├── ak.png │ ├── create.png │ ├── createprimary.png │ ├── ek.png │ ├── evictcontrol.png │ ├── hierarchies.png │ ├── nvdefine.png │ ├── nvdefinepcrpolicy.png │ ├── nvpcrpolicy.png │ └── nvwrite.png ├── commandSummary.md ├── eltt2.md ├── exercises.md ├── gotpm.md ├── gotpm_quote.md ├── keys.md ├── nvram.md ├── objects.md ├── pcrs.md ├── quoting.md └── random.md └── src └── gotpm_quote.go /.github/workflows/book.yml: -------------------------------------------------------------------------------- 1 | name: Book 2 | 3 | on: 4 | push: 5 | branches: ["master"] 6 | 7 | permissions: 8 | contents: read 9 | pages: write 10 | id-token: write 11 | 12 | concurrency: 13 | group: "pages" 14 | cancel-in-progress: false 15 | 16 | jobs: 17 | deploy: 18 | environment: 19 | name: Book 20 | url: ${{ steps.deployment.outputs.page_url }} 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v3 25 | - name: Setup Pages 26 | uses: actions/configure-pages@v3 27 | - name: Setup mdbook 28 | uses: peaceiris/actions-mdbook@v1.2.0 29 | - run: mdbook build 30 | - name: Upload artifacts 31 | uses: actions/upload-pages-artifact@v2 32 | with: 33 | path: 'book' 34 | - name: Deploy to GitHub Pages 35 | id: deployment 36 | uses: actions/deploy-pages@v2 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Clear BSD License 2 | 3 | Copyright (c) 2020 Nokia 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted (subject to the limitations in the disclaimer 8 | below) provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from this 19 | software without specific prior written permission. 20 | 21 | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY 22 | THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 23 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 30 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nokia TPM Course 2 | 3 | This is a short course on getting started with understanding how a TPM 2.0 works. In this course we explain a number of the features of the TPM 2.0 through the TPM2_Tools through examples and, optionally, exercises. 4 | 5 | While this course is designed to be used as part of a tutorial session it can be used stand alone and also as an easy reference. 6 | 7 | (C)2022 Nokia 8 | 9 | ## Installation 10 | 11 | There are other ways to complete the install, other ways to do each step, but this is common and clear. 12 | 13 | Start your install at a terminal window on a linux system. If you are using a Windows computer, create a linux VM (possibly using VirtualBox), such as the latest Ubuntu system, and begin your install from the linux VM command line. 14 | 15 | While in your home directory, install the TPMCourse in your linux VM by using git. The command is 16 | 17 | ```bash 18 | git clone https://github.com/nokia/TPMCourse.git 19 | ``` 20 | 21 | Git will clone (copy) files from the remote TPMCourse repository on the Nokia github to your linux system. However, your linux system may not yet have the git tool. If you don't have it, you will need to install it in order to complete the git clone. (The linux system should tell you how to install it as part of its negative response to your initial attempt.) 22 | https://git-scm.com/book/en/v2/Getting-Started-Installing-Git 23 | 24 | When the clone is complete, your home directory should have a new TPMCourse sub-directory. Move to this directory on your linux system and list the files and directories. It should look like the Nokia github TPMCourse repository from which you copied, including an alpine directory, a docs directory, a src directory, a license file and a README file. Now you are ready to build the container that will host the TPM simulator, the TPM tools, and the alpine linux operating system which is a simple secure linux that will always have the libraries and configurations needed for this course. 25 | 26 | Note, for now, let's assume you are going to work on a TPM Simulator, not an actual TPM in your system hardware. This course could be adapted to work with a real TPM, but that will not be addressed here. The TPM simulator is convenient for learning, because if you mess up something, only the simulator is affected and the simulator can easily be restored (by restart). 27 | 28 | To build the TPMCourse container, docker must be available on your linux VM. If you enter the docker build command below and it starts the 29 step build, you are on your way. If it fails, the system will provide the instructions on how to install docker on your system. After docker install, you may receive "Got permission denied while trying to connect to the Docker daemon socket...". If so, you have a permission issue. See "How to Fix Docker Permission Denied Error on Ubuntu": 29 | https://linuxhandbook.com/docker-permission-denied/#:~:text=deal%20with%20it.-,Fix%201%3A%20Run%20all%20the%20docker%20commands%20with%20sudo,the%20Docker%20daemon%20socket'%20anymore. 30 | 31 | 32 | ```bash 33 | cd alpine 34 | docker build -t tpmcourse:latest . 35 | ``` 36 | 37 | NOTE: the above might need to be run as sudo, eg: 38 | 39 | ```bash 40 | sudo docker build -t tpmcourse:latest . 41 | ``` 42 | 43 | 44 | To see how the build executes, see the Dockerfile in the alpine directory which when built downloads the various libraries and tools to interact with a TPM and also the IBM TPM Simulator 45 | 46 | If all works successfully, after about 29 stages, you can type the following command to run the container in interactive mode. 47 | 48 | ```bash 49 | docker run -it tpmcourse:latest 50 | ``` 51 | 52 | NOTE: the above might need to be run as sudo, eg: 53 | 54 | ```bash 55 | sudo docker run -it tpmcourse:latest 56 | ``` 57 | 58 | 59 | The following will be printed out. This tells us that the TPM simulator is runnig on ports 2321 and 2322 and at the end we have a command line prompt. We're running the `ash` command line interpreter. 60 | 61 | ``` 62 | / # LIBRARY_COMPATIBILITY_CHECK is ON 63 | Manufacturing NV state... 64 | Size of OBJECT = 2600 65 | Size of components in TPMT_SENSITIVE = 1096 66 | TPMI_ALG_PUBLIC 2 67 | TPM2B_AUTH 66 68 | TPM2B_DIGEST 66 69 | TPMU_SENSITIVE_COMPOSITE 962 70 | Starting ACT thread... 71 | TPM command server listening on port 2321 72 | Platform server listening on port 2322 73 | Command IPv4 client accepted 74 | Platform IPv4 client accepted 75 | ^C 76 | / # 77 | ``` 78 | 79 | NOTE: sometimes the `#`` prompt doesn't appear...hit enter, the it should. 80 | 81 | To test type the TPM command `tpm2_getrandom` to obtain a random number: 82 | 83 | ```bash 84 | tpm2_getrandom 32 --hex 85 | e0b2c1bb096a81032ec1114cc504795ee77c7cc3d159e76165801b38d892296f 86 | / # 87 | ``` 88 | 89 | NB: you should get a different random number that we do above! 90 | 91 | ## Caveats 92 | 93 | Firstly, you can run everything here against your own, real, hardware (or firmware) TPM - there are some commands which might be irreperable changes - these are clearly noted. We are NOT responsible for any actions resulting in the bricking or worse of your (or someone else's) computer. 94 | 95 | The supplied docker file is the best way to explore things in safety...if you break something you can just restart the container :-) 96 | 97 | Secondly, sometimes parameters to commands change - we use the latest tpm2_tools and sometimes things do change and the course might not be fully updated. In this case, either make an issue in github or make a fork, change and then a pull request - your contributions either way will be very much appreciated. 98 | 99 | 100 | ## Course Material 101 | 102 | All the course material is in the [./docs](./docs) directory. Read the `STARTHERE.md` file first and then work through the documents in order. You can find a set of files that explain different TPM concepts and contain code examples you can use with the container to get familiarized with TPM and its use cases. 103 | 104 | 105 | ## Technologies 106 | 107 | Software needed for the actual end functionality is the TCG TPM2 Software Stack 108 | (TSS2) and the IBM TPM simulator. 109 | 110 | * [TPM2-tss](https://github.com/tpm2-software/tpm2-tss) BSD-2-Clause 111 | * [TPM2-abrmd](https://github.com/tpm2-software/tpm2-abrmd) BSD-2-Clause 112 | * [TPM2-tools](https://github.com/tpm2-software/tpm2-tools) BSD-3-Clause 113 | * [IBM simulator](./licenses/LICENSE-ibm-tpm-simulator) 114 | 115 | 116 | -------------------------------------------------------------------------------- /alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | #TPM2 simulator with alpine base 2 | FROM alpine:3.13.6 3 | LABEL Maintainer="Ronny Backman " 4 | LABEL version="1.0" 5 | LABEL description="Base image for running TPM2 Software Stack (TSS), Access \ 6 | Broker & Resource Management Daemon (ABRMD) and tools against IBM tpm simulator" 7 | 8 | ENV LC_ALL C.UTF-8 9 | ENV LANG C.UTF-8 10 | ENV LANGUAGE C.UTF-8 11 | 12 | COPY open-source-tpm-alpine-spdx.rdf / 13 | 14 | # Installing needed dependecies and tools for developing 15 | 16 | RUN apk update && \ 17 | apk add \ 18 | acl \ 19 | autoconf \ 20 | autoconf-archive \ 21 | automake \ 22 | libtool \ 23 | build-base \ 24 | pkgconf \ 25 | doxygen \ 26 | json-c-dev \ 27 | openssl \ 28 | openssl-dev \ 29 | libssl1.1 \ 30 | git \ 31 | udev \ 32 | dbus \ 33 | curl-dev \ 34 | linux-headers \ 35 | glib-dev \ 36 | libconfig-dev \ 37 | libgcrypt-dev \ 38 | shadow \ 39 | wget 40 | 41 | RUN mkdir tpm2 42 | WORKDIR /tpm2 43 | RUN mkdir ibmsim 44 | 45 | WORKDIR /tpm2 46 | RUN git clone --branch 3.0.x https://github.com/tpm2-software/tpm2-tss.git && \ 47 | git clone https://github.com/tpm2-software/tpm2-abrmd.git && \ 48 | git clone https://github.com/tpm2-software/tpm2-tools.git 49 | 50 | WORKDIR /tpm2/tpm2-tss 51 | RUN ./bootstrap && \ 52 | ./configure --with-udevrulesprefix && \ 53 | make -j4 && \ 54 | make install 55 | 56 | WORKDIR /tpm2/tpm2-abrmd 57 | RUN ./bootstrap && \ 58 | ./configure --with-dbuspolicydir=/etc/dbus-1/system.d && \ 59 | make -j4 && \ 60 | make install 61 | 62 | WORKDIR /tpm2/tpm2-tools 63 | RUN ./bootstrap && \ 64 | ./configure && \ 65 | make -j4 && \ 66 | make install 67 | 68 | 69 | WORKDIR /tpm2/ibmsim 70 | RUN wget --quiet --show-progress --progress=dot:giga --no-check-certificate "https://downloads.sourceforge.net/project/ibmswtpm2/ibmtpm1661.tar.gz" 71 | RUN tar -xf ibmtpm1661.tar.gz 72 | WORKDIR /tpm2/ibmsim/src 73 | RUN make -j4 74 | RUN cp tpm_server /bin/ 75 | 76 | 77 | WORKDIR / 78 | 79 | COPY tpmStartup.sh /bin/ 80 | 81 | CMD ["tpmStartup.sh"] 82 | -------------------------------------------------------------------------------- /alpine/README.md: -------------------------------------------------------------------------------- 1 | # TPM 2.0 alpine container 2 | 3 | NB: Refer to the README.md in the main directory for installation and usage instructions 4 | 5 | The base image for the container is **alpine:latest**. 6 | 7 | Dependecies for building the TCG TPM2 Software Stack are: 8 | 9 | * autoconf 10 | * autoconf-archive 11 | * automake 12 | * libtool 13 | * build-base 14 | * pkgconf 15 | * doxygen 16 | * json-c-dev 17 | * openssl 18 | * openssl-dev 19 | * libssl1.1 20 | * git 21 | * udev 22 | * dbus 23 | * curl-dev 24 | * linux-headers 25 | * glib-dev 26 | * libconfig-dev 27 | * libgcrypt-dev 28 | * wget 29 | 30 | It is possible to further strip down dependecies, some packages are only used for 31 | building the documentation which is not in use inside the container as 32 | default. 33 | 34 | -------------------------------------------------------------------------------- /alpine/tpmStartup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Start dbus service and sleep for 1 second to wait that it has started. 4 | # If tpm2-abrmd starts before the dbus service is ready we get an error. 5 | dbus-daemon --system & 6 | sleep 1 7 | 8 | # Start the ibm tpm simulator with default settings 9 | tpm_server & 10 | 11 | # Start tpm2 access broker & resource manager daemon 12 | tpm2-abrmd --allow-root --tcti=mssim & 13 | 14 | # Continue with a shell as default 15 | ash 16 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Patrick Elsen"] 3 | language = "en" 4 | multilingual = false 5 | src = "docs" 6 | title = "Nokia TPM Course" 7 | -------------------------------------------------------------------------------- /docs/Crim2022Tutorial/README.md: -------------------------------------------------------------------------------- 1 | # CRIM 2022 Tutorial Exercises 2 | 3 | In this directory you will find the Crim 2022 Tutorial Exercises. The document is a LaTeX file and can be compiled with `pdflatex`. Check the hash too (and any github commits; the tutorial was uploaded by ianolivergithub at 22h35 (EET) on 6 November 2022. Anything different suggests tampering 4 | 5 | ```bash 6 | $ sha256sum tutorial.tex 7 | 15434669ed227908dcfe3d4a138fda812bcde0cec0225164a4d548277ecb52a6 tutorial.tex 8 | $ pdflatex tutorial.tex 9 | ``` 10 | 11 | The result should be `tutorial.pdf` 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/Crim2022Tutorial/tutorial.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,a4paper]{article} 2 | 3 | \usepackage[margin=1in]{geometry} 4 | %\usepackage{parskip} 5 | \setlength{\parindent}{0pt} 6 | \setlength{\parskip}{10pt} 7 | 8 | \begin{document} 9 | 10 | \title{TPM and Attestation Tutorial} 11 | \author{Ian Oliver\\Crim 2022, Oulu} 12 | \maketitle 13 | 14 | \tableofcontents 15 | 16 | \section{Installation} 17 | 18 | \textit{NOTE: some familiarity with Linux is assumed. Docker should run on Windows, I have never tried. If you want to remain in a pure Windows world, again I have no idea, though I would strongly recommend you do not do this, especially if using things like Bitlocker. MacOS - again no idea. Raspberry Pis - if you are lucky enough to have a TPM module then it is basically the same as any other Linux.} 19 | 20 | The TPM Course and docker images can be found at https://github.com/nokia/TPMCourse. Either download the zip file or use git clone. 21 | 22 | Go to the docs directory and start with README.md then progress through the tutorial becomming familiar with the commands. 23 | 24 | There are two ways in which you can do this: 25 | \begin{itemize} 26 | \item use a docker container with a software TPM and all the tools 27 | \item use your own TPM 28 | \end{itemize} 29 | 30 | \subsection{Installation using Docker} 31 | 32 | If you need Docker, first go here: https://docs.docker.com/engine/install/ 33 | 34 | Use the follwoing command (change to the alpine directory in the tutorial) 35 | 36 | \texttt{sudo docker build -t tpmcourse:latest .} 37 | 38 | Take a while to compile; the last few steps look like this: 39 | 40 | \begin{verbatim} 41 | Step 28/29 : COPY tpmStartup.sh /bin/ 42 | ---> 20e8e3ae5ba2 43 | Step 29/29 : CMD ["tpmStartup.sh"] 44 | ---> Running in f0503d249a58 45 | Removing intermediate container f0503d249a58 46 | ---> ddadb286c839 47 | Successfully built ddadb286c839 48 | Successfully tagged tpmcourse:latest 49 | \end{verbatim} 50 | 51 | 52 | To run type \texttt{sudo docker run --network host -it tpmcourse:latest} 53 | 54 | NOTE: You need to explicitly allow networking from the container!! 55 | 56 | This will start and look like this: (if the Linux \# prompt doesn't appear just hit enter) 57 | 58 | \begin{verbatim} 59 | $ sudo docker run -it tpmcourse:latest 60 | / # LIBRARY_COMPATIBILITY_CHECK is ON 61 | Manufacturing NV state... 62 | Size of OBJECT = 2600 63 | Size of components in TPMT_SENSITIVE = 1096 64 | TPMI_ALG_PUBLIC 2 65 | TPM2B_AUTH 66 66 | TPM2B_DIGEST 66 67 | TPMU_SENSITIVE_COMPOSITE 962 68 | Starting ACT thread... 69 | TPM command server listening on port 2321 70 | Platform server listening on port 2322 71 | Command IPv4 client accepted 72 | Platform IPv4 client accepted 73 | 74 | / # 75 | \end{verbatim} 76 | 77 | Type \texttt{tpm2\_getrandom --hex 16} and you should see something like this: 78 | 79 | \begin{verbatim} 80 | # tpm2_getrandom --hex 16 81 | 27706ef869838058eb9b0203a3d2bfcd/ # 82 | \end{verbatim} 83 | 84 | Congratulations you now have a docker image with a working software TPM - no chance of doing serious damage :-) 85 | 86 | \subsection{Running Against a Real TPM} 87 | 88 | WARNING: if you are not comfortable doing this then use the docker container. 89 | 90 | If your laptop (and all do) has a TPM (and you're running Linux) you can check this by typing 91 | 92 | \begin{verbatim} 93 | $ ls /dev/tpm* 94 | /dev/tpm0 95 | /dev/tpmrm0 96 | \end{verbatim} 97 | 98 | 99 | If these devices are missing then it is likely that the TPM is turned off the UEFI/BIOS. One some machines this is called the "security chip". 100 | 101 | To install the TPM2 Tools you can use sudo apt install tpm2-tools which will install version 5 on most Linux distributions, for example Debian/Ubuntu: 102 | 103 | \begin{verbatim} 104 | $ apt search tpm2 105 | Sorting... Done 106 | Full Text Search... Done 107 | 108 | tpm2-tools/stable 5.0-2 amd64 109 | TPM 2.0 utilities 110 | 111 | $ sudo apt install tpm2-tools 112 | \end{verbatim} 113 | 114 | 115 | Or compile from source: first you need to compile tpm2-tss, tpm2-abrmd and then tpm2-tools: https://github.com/tpm2-software/tpm2-tools 116 | 117 | \section{Basic Commands} 118 | 119 | Follow the tutorial commands outlined in the tutorial: 120 | 121 | \begin{itemize} 122 | \item Random 123 | \item Objects 124 | \item Keys 125 | \item NVRAM 126 | \item PCRs 127 | \item Quoting 128 | \end{itemize} 129 | 130 | \section{Exercise - Generate EK and AK} 131 | \textbf{NOTE: if you are using the TPM simualator via the docker container, you will lose these if you exit the docker container. Good news is you'll get practice recreating them if you do this} 132 | 133 | We have an attestation server running - this is a lot more exciting if you are using your own PC with a TPM, but with a software TPM almost. Firstly make sure you can ping the attestation server's REST API and view the user interface (instructions on this during the tutorial session). 134 | 135 | In order to enroll your machine in the attestation server you will need to construct a JSON object like this: 136 | 137 | \begin{verbatim} 138 | { 139 | "description": "EDIT_THIS_LONGER_DESCRIPTION", 140 | "endpoint": "http://127.0.0.1:8530", 141 | "name": "EDIT_THIS", 142 | "protocol": "A10HTTPREST", 143 | "type": [ 144 | "tpm2.0", 145 | "TPM3", 146 | "xxx" 147 | ] 148 | } 149 | \end{verbatim} 150 | 151 | You can either create this using the web UI or using a text editor locally and using the REST API with curl. Change the fields description, endpoint, name and make a short list of entries in the type list. 152 | 153 | To find your IP address type ip addr at the console. On mine it looks like this and you generally need the Wifi/cable interface with a name like "ens33" in this case: 154 | 155 | \begin{verbatim} 156 | # ip addr 157 | 1: lo: mtu 65536 qdisc noqueue state UNKNOWN qlen 1000 158 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 159 | inet 127.0.0.1/8 scope host lo 160 | valid_lft forever preferred_lft forever 161 | inet6 ::1/128 scope host 162 | valid_lft forever preferred_lft forever 163 | 2: ens33: mtu 1500 qdisc pfifo_fast state UP qlen 1000 164 | link/ether 00:0c:29:c9:0b:16 brd ff:ff:ff:ff:ff:ff 165 | inet 192.168.1.33/24 brd 192.168.1.255 scope global dynamic ens33 166 | valid_lft 84449sec preferred_lft 84449sec 167 | inet6 fe80::20c:29ff:fec9:b16/64 scope link 168 | valid_lft forever preferred_lft forever 169 | 3: docker0: mtu 1500 qdisc noqueue state DOWN 170 | link/ether 02:42:20:33:4e:e1 brd ff:ff:ff:ff:ff:ff 171 | inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 172 | valid_lft forever preferred_lft forever 173 | inet6 fe80::42:20ff:fe33:4ee1/64 scope link 174 | valid_lft forever preferred_lft forever 175 | \end{verbatim} 176 | 177 | 178 | So my endpoint field becomes: \texttt{http://192.168.1.33:8530} 179 | 180 | What we need to do is add a field to the above to describe the TPM. It looks like this (your values will be different). 181 | 182 | You need to make two keys, the EK and the AK and extract information from these. 183 | 184 | Create the EK and place it in handles \textbf{0x810100ee} and the AK in \textbf{0x810100aa} 185 | 186 | \textbf{NOTE: take note of which handles you used for the above keys!! If you created the EK and AK earlier then you can use those handles too. Remember the caveat about exiting the docker container} 187 | 188 | \textbf{NOTE: The attestation server DOES NOT do an JSON validation - it will show a crash page. Just hit the back button and re enter. A GOOD HINT is to use a text editor or a JSON validator site to ge the below correct and then copy and paste it into the attesation engine UI} 189 | 190 | \begin{verbatim} 191 | "tpm2": { "tpm0": { 192 | "akhandle": "0x810100aa", 193 | "akname": "000b6cd38416fbfadebd7c4312a7dd382d8e4f95449d5c5410c3148d3ba972340da1", 194 | "akpem": "-----BEGIN PUBLIC KEY-----\nMIIBIjAN 195 | 196 | QbBoFA8Y/w\nWQIDAQAB\n-----END PUBLIC KEY-----\n", 197 | "ekhandle": "0x810100ee", 198 | "ekname": "000b59ff58093c05599af508562c840430dd74a7e78784da1abadf7ef4d9811a38e4", 199 | "ekpem": "-----BEGIN PUBLIC KEY-----\nMIIBIjAN 200 | 201 | AQAB\n-----END PUBLIC KEY-----\n" 202 | } 203 | } 204 | \end{verbatim} 205 | 206 | 207 | 208 | Bonus points for finding out if your laptop made a measured boot in UEFI mode. If so add this field too: 209 | 210 | \begin{verbatim} 211 | "uefi": { 212 | "eventlog": "/sys/kernel/security/tpm0/binary_bios_measurements" 213 | } 214 | \end{verbatim} 215 | 216 | 217 | Create your entry in the attestation server! 218 | 219 | \section{Running a Trust Agent} 220 | 221 | The attestation server needs to communicate with your TPM. You can find it here: https://github.com/nokia/AttestationEngine and use git or download the zip. For example: 222 | 223 | \begin{verbatim} 224 | # git clone https://github.com/nokia/AttestationEngine.git 225 | Cloning into 'AttestationEngine'... 226 | remote: Enumerating objects: 6621, done. 227 | remote: Counting objects: 100% (1364/1364), done. 228 | remote: Compressing objects: 100% (645/645), done. 229 | remote: Total 6621 (delta 650), reused 1208 (delta 634), pack-reused 5257 230 | Receiving objects: 100% (6621/6621), 7.89 MiB | 5.79 MiB/s, done. 231 | Resolving deltas: 100% (3575/3575), done. 232 | \end{verbatim} 233 | 234 | 235 | The directory you want is \texttt{t10/nut10} inside this distribution 236 | 237 | If you are running on plain Linux then you will need to ensure python3 and pip3 are installed and then ensure that the python packages flask and pyyaml are also there 238 | 239 | \begin{verbatim} 240 | pip3 install flask 241 | pip3 install pyyaml 242 | \end{verbatim} 243 | 244 | 245 | On the docker container you need to run the following commands: 246 | 247 | \begin{verbatim} 248 | apk add py3-pip 249 | pip3 install flask 250 | pip3 install pyyaml 251 | \end{verbatim} 252 | 253 | To run the trust agent you need to be administrator/sudo. In the docker container you are already the admin 254 | 255 | \texttt{python3 ta.py} 256 | 257 | You can check if it is working by typing \texttt{http://:8530}into a browser, you should get a description of the trust agent back. 258 | 259 | \section{Exercise - Collect PCRs} 260 | Now go to the attestation server and try collecting the PCRs for your device. 261 | 262 | 263 | \section{Exercise - Modify PCRs} 264 | Stop the trust agent and modify some of the PCRs however you wish. On a normal laptop only PCRs 16 and 23 should be modified with \texttt{tpm2\_extend} or \texttt{tpm2\_event} (bonus: what's the difference between these commands?) 265 | 266 | \section{Exercise - Quotes} 267 | Using quotes find out some expected values for your machine - for a live TPM these values are in PCRs 0 through to 7 and describe how your machine booted - the policies are called CRTM, SRTM etc. 268 | 269 | Find the itemid for your machine from the attestation server UI and also the policy itemid. Then create an expected value for your machine. They look like this but your fields will differ. Give the name something very obvious to yourselves. Obviously change the elementID and policyID fields!!! 270 | 271 | \begin{verbatim} 272 | { 273 | "description": "Ian laptop CRTM Value", 274 | "elementID": "37429f53-c3c2-447d-b6b7-d515c916c179", 275 | "evs": { 276 | "firmwareVersion": "2a1aa04410004700", 277 | "pcrDigest": "a0c06cb059eb8ebf217b6dbab55297a352fc69c2000273b33914003cfbbe3117" 278 | }, 279 | 280 | "name": "Ian CRTM", 281 | "policyID": "2af3b502-b3b4-4c7b-a021-11c4d8224e4f", 282 | "type": "tpm2_attestedValuePCRdigest" 283 | } 284 | \end{verbatim} 285 | 286 | 287 | Before you submit this from the quote you just made (see the attestation claims page) find the firmware version of your TPM and the pcrDigest for that particular attestation. 288 | 289 | Remember to restart the trust agent! 290 | 291 | \section{Exercise - Attest, Change, Reboot, Update, Attest} 292 | \textbf{NOTE: if you used 0x810100AA for atteststion key then good, if not then you need to enter this into the call parameters section of the atteststion server UI page} 293 | 294 | Change some PCRs, reboot your laptop, maybe even make an update if you're running outside of a container, eg: \texttt{sudo apt update} followed by \texttt{sudo apt upgrade}. Bonus if this invoves an update to the kernel. 295 | 296 | Reattest. 297 | 298 | What changed? 299 | 300 | \section{Exercise - Forensics} 301 | Go to the forensics capture interface. Explore what went on there? 302 | 303 | 304 | 305 | \end{document} 306 | -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/booted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/Crim2023Tutorial/booted.png -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/gitdownload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/Crim2023Tutorial/gitdownload.png -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/profilesetup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/Crim2023Tutorial/profilesetup.png -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/rebootnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/Crim2023Tutorial/rebootnow.png -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/selectiso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/Crim2023Tutorial/selectiso.png -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/sshserver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/Crim2023Tutorial/sshserver.png -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/Crim2023Tutorial/success.png -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/tutorial2023.aux: -------------------------------------------------------------------------------- 1 | \relax 2 | \@writefile{toc}{\contentsline {section}{\numberline {1}Installation}{1}{}\protected@file@percent } 3 | \@writefile{toc}{\contentsline {section}{\numberline {2}Tutorial and TPM Familiarity}{2}{}\protected@file@percent } 4 | \newlabel{theexercises}{{2}{2}} 5 | \@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Basic Commands}{2}{}\protected@file@percent } 6 | \@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Command Parameters}{2}{}\protected@file@percent } 7 | \newlabel{commandparameters}{{2.2}{2}} 8 | \@writefile{toc}{\contentsline {subsection}{\numberline {2.3}TPM Memory and Flush Context}{3}{}\protected@file@percent } 9 | \newlabel{flush}{{2.3}{3}} 10 | \@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Communicating with the TPM}{3}{}\protected@file@percent } 11 | \@writefile{toc}{\contentsline {section}{\numberline {3}Exercises}{3}{}\protected@file@percent } 12 | \@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Generate Keys}{3}{}\protected@file@percent } 13 | \@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Generate and EK and AK}{4}{}\protected@file@percent } 14 | \@writefile{toc}{\contentsline {subsection}{\numberline {3.3}PCRs}{4}{}\protected@file@percent } 15 | \newlabel{pcrs}{{3.3}{4}} 16 | \@writefile{toc}{\contentsline {subsection}{\numberline {3.4}UEFI EventLog}{4}{}\protected@file@percent } 17 | \@writefile{toc}{\contentsline {subsection}{\numberline {3.5}Quotes}{5}{}\protected@file@percent } 18 | \@writefile{toc}{\contentsline {subsection}{\numberline {3.6}Updates}{5}{}\protected@file@percent } 19 | \gdef \@abspage@last{5} 20 | -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/tutorial2023.log: -------------------------------------------------------------------------------- 1 | This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/Debian) (preloaded format=pdflatex 2023.6.4) 13 NOV 2023 17:08 2 | entering extended mode 3 | restricted \write18 enabled. 4 | %&-line parsing enabled. 5 | **tutorial2023.tex 6 | (./tutorial2023.tex 7 | LaTeX2e <2022-11-01> patch level 1 8 | L3 programming layer <2023-01-16> 9 | (/usr/share/texlive/texmf-dist/tex/latex/base/article.cls 10 | Document Class: article 2022/07/02 v1.4n Standard LaTeX document class 11 | (/usr/share/texlive/texmf-dist/tex/latex/base/size11.clo 12 | File: size11.clo 2022/07/02 v1.4n Standard LaTeX file (size option) 13 | ) 14 | \c@part=\count185 15 | \c@section=\count186 16 | \c@subsection=\count187 17 | \c@subsubsection=\count188 18 | \c@paragraph=\count189 19 | \c@subparagraph=\count190 20 | \c@figure=\count191 21 | \c@table=\count192 22 | \abovecaptionskip=\skip48 23 | \belowcaptionskip=\skip49 24 | \bibindent=\dimen140 25 | ) 26 | (/usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty 27 | Package: geometry 2020/01/02 v5.9 Page Geometry 28 | 29 | (/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty 30 | Package: keyval 2022/05/29 v1.15 key=value parser (DPC) 31 | \KV@toks@=\toks16 32 | ) 33 | (/usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty 34 | Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead. 35 | 36 | (/usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty 37 | Package: iftex 2022/02/03 v1.0f TeX engine tests 38 | )) 39 | \Gm@cnth=\count193 40 | \Gm@cntv=\count194 41 | \c@Gm@tempcnt=\count195 42 | \Gm@bindingoffset=\dimen141 43 | \Gm@wd@mp=\dimen142 44 | \Gm@odd@mp=\dimen143 45 | \Gm@even@mp=\dimen144 46 | \Gm@layoutwidth=\dimen145 47 | \Gm@layoutheight=\dimen146 48 | \Gm@layouthoffset=\dimen147 49 | \Gm@layoutvoffset=\dimen148 50 | \Gm@dimlist=\toks17 51 | ) 52 | (/usr/share/texlive/texmf-dist/tex/latex/url/url.sty 53 | \Urlmuskip=\muskip16 54 | Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. 55 | ) 56 | (/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def 57 | File: l3backend-pdftex.def 2023-01-16 L3 backend support: PDF output (pdfTeX) 58 | \l__color_backend_stack_int=\count196 59 | \l__pdf_internal_box=\box51 60 | ) 61 | (./tutorial2023.aux) 62 | \openout1 = `tutorial2023.aux'. 63 | 64 | LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 9. 65 | LaTeX Font Info: ... okay on input line 9. 66 | LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 9. 67 | LaTeX Font Info: ... okay on input line 9. 68 | LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 9. 69 | LaTeX Font Info: ... okay on input line 9. 70 | LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 9. 71 | LaTeX Font Info: ... okay on input line 9. 72 | LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 9. 73 | LaTeX Font Info: ... okay on input line 9. 74 | LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 9. 75 | LaTeX Font Info: ... okay on input line 9. 76 | LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 9. 77 | LaTeX Font Info: ... okay on input line 9. 78 | 79 | *geometry* driver: auto-detecting 80 | *geometry* detected driver: pdftex 81 | *geometry* verbose mode - [ preamble ] result: 82 | * driver: pdftex 83 | * paper: a4paper 84 | * layout: 85 | * layoutoffset:(h,v)=(0.0pt,0.0pt) 86 | * modes: 87 | * h-part:(L,W,R)=(72.26999pt, 452.9679pt, 72.26999pt) 88 | * v-part:(T,H,B)=(72.26999pt, 700.50687pt, 72.26999pt) 89 | * \paperwidth=597.50787pt 90 | * \paperheight=845.04684pt 91 | * \textwidth=452.9679pt 92 | * \textheight=700.50687pt 93 | * \oddsidemargin=0.0pt 94 | * \evensidemargin=0.0pt 95 | * \topmargin=-37.0pt 96 | * \headheight=12.0pt 97 | * \headsep=25.0pt 98 | * \topskip=11.0pt 99 | * \footskip=30.0pt 100 | * \marginparwidth=50.0pt 101 | * \marginparsep=10.0pt 102 | * \columnsep=10.0pt 103 | * \skip\footins=10.0pt plus 4.0pt minus 2.0pt 104 | * \hoffset=0.0pt 105 | * \voffset=0.0pt 106 | * \mag=1000 107 | * \@twocolumnfalse 108 | * \@twosidefalse 109 | * \@mparswitchfalse 110 | * \@reversemarginfalse 111 | * (1in=72.27pt=25.4mm, 1cm=28.453pt) 112 | 113 | LaTeX Font Info: External font `cmex10' loaded for size 114 | (Font) <12> on input line 13. 115 | LaTeX Font Info: External font `cmex10' loaded for size 116 | (Font) <8> on input line 13. 117 | LaTeX Font Info: External font `cmex10' loaded for size 118 | (Font) <6> on input line 13. 119 | (./tutorial2023.toc 120 | LaTeX Font Info: External font `cmex10' loaded for size 121 | (Font) <10.95> on input line 3. 122 | ) 123 | \tf@toc=\write3 124 | \openout3 = `tutorial2023.toc'. 125 | 126 | [1 127 | 128 | {/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] 129 | [2] 130 | Overfull \hbox (137.07434pt too wide) in paragraph at lines 83--84 131 | \OT1/cmr/m/n/10.95 ment vari-able to di-rect com-mands to the sim-u-la-tor. Set 132 | this \OT1/cmtt/m/n/10.95 export TPM2TOOLS[]TCTI="mssim:host=localhost,port=232 133 | 1" 134 | [] 135 | 136 | [3] [4] [5] (./tutorial2023.aux) ) 137 | Here is how much of TeX's memory you used: 138 | 1170 strings out of 477975 139 | 19756 string characters out of 5839282 140 | 1857330 words of memory out of 5000000 141 | 21354 multiletter control sequences out of 15000+600000 142 | 518313 words of font info for 52 fonts, out of 8000000 for 9000 143 | 59 hyphenation exceptions out of 8191 144 | 57i,6n,62p,419b,206s stack positions out of 10000i,1000n,20000p,200000b,200000s 145 | 151 | 153 | Output written on tutorial2023.pdf (5 pages, 124733 bytes). 154 | PDF statistics: 155 | 60 PDF objects out of 1000 (max. 8388607) 156 | 37 compressed objects within 1 object stream 157 | 0 named destinations out of 1000 (max. 500000) 158 | 1 words of extra memory for PDF output out of 10000 (max. 10000000) 159 | 160 | -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/tutorial2023.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/Crim2023Tutorial/tutorial2023.pdf -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/tutorial2023.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt,a4paper]{article} 2 | 3 | \usepackage[margin=1in]{geometry} 4 | %\usepackage{parskip} 5 | \usepackage{url} 6 | \setlength{\parindent}{0pt} 7 | \setlength{\parskip}{10pt} 8 | 9 | \begin{document} 10 | 11 | \title{TPM Tutorial Worksheet} 12 | \author{Ian Oliver\\Crim 2023\\November 16th 2023\\University of Oulu} 13 | \maketitle 14 | 15 | \tableofcontents 16 | 17 | 18 | \section{Installation} 19 | The course is found at \url{https://github.com/nokia/TPMCourse}. The README file contains the installation instructions carefully and make sure that you have this working before the tutorial. \textbf{READ THE INSTRUCTIONS CAREFULLY}. 20 | 21 | The docker based installation has been tested in Linux (various Ubuntus and Debians). 22 | 23 | If you are running on Windows, Mac or something even more exotic (you mean you don't an IBM zSeries at home?!) then it is probably much easier to build a virtual machine using VMWare Player or VirtualBox. Download Ubuntu desktop or server as you wish (Desktop has a nice UI!) and install and run it in your VM. 24 | 25 | For those of you who can unpick the Dockerfile and figure out how to install everything on a bare-metal Linux box with a real TPM...good luck. If you brick your TPM, corrupt your OS, lose encryption keys or anything else, I did warn you and take no responsibility. 26 | 27 | Once you get it working proceed to the exercises in section \ref{theexercises} of this document - it is immediately after this. 28 | 29 | 30 | 31 | \section{Tutorial and TPM Familiarity}\label{theexercises} 32 | Read each section carefully and take notes as you go along. If you break your simulated TPM, exit docker and restart. Note, if you had keys or data in that simulated TPM it will be lost on each startup. 33 | 34 | Good Advice: keep a log of each command you run in a separate textfile - easy to copy and paste these back in later and also makes debugging easier. 35 | 36 | 37 | \subsection{Basic Commands} 38 | Follow the tutorial commands outlined in the tutorial in this order. You will find these files under the `docs` director of the downloaded course or directly on the Github pages at \url{https://github.com/nokia/TPMCourse/blob/master/docs/STARTHERE.md} 39 | 40 | Take note of the warning in section \ref{commandparameters} below. 41 | 42 | Take notes as you go along, \textbf{draw pictures}, keep a log of commands and don't be afraid to restart the simulator if you need. 43 | 44 | \begin{itemize} 45 | \item Random 46 | \item Objects 47 | \item Keys (see section \ref{flush} below) 48 | \item NVRAM 49 | \item PCRs 50 | \item Quoting 51 | \end{itemize} 52 | 53 | \subsection{Command Parameters}\label{commandparameters} 54 | Sometimes parameters to commands change - we use the latest TPM2 Tools and sometimes things do change and the course might not be fully updated. In this case, either make an issue in github or make a fork, change and then a pull request - your contributions either way will be very much appreciated. 55 | 56 | 57 | \subsection{TPM Memory and Flush Context}\label{flush} 58 | This can also be found in the section on key generation, but I will repeat it here. See also \url{https://github.com/nokia/TPMCourse/blob/master/docs/keys.md#tpm-memory} 59 | 60 | TPMs have limited space for storing objects such as keys, session information etc. Different manufacturers provide different amounts of space and in some cases even behaviours when dealing with temporary objects. The IBM TPM Simulator used in the Dockerfiles has very limited storage and you'll find objects being left in the transient memory space. 61 | 62 | If you receive out of memory errors from the simulator or any TPM then check if there are objects (typically keys) in the transient memory area; for example we can use \texttt{tpm2\_getcap} to display this and in this example we have two objects in the transient area. 63 | 64 | \begin{verbatim} 65 | $tpm2_getcap handles-transient 66 | 0x80000000 67 | 0x80000001 68 | \end{verbatim} 69 | 70 | To remove these objects use the command \texttt{tpm2\_flushcontext -t} and check with \texttt{tpm2\_getcap} again - if nothing is reported then all worked. 71 | 72 | \begin{verbatim} 73 | $tpm2_getcap handles-transient 74 | 0x80000000 75 | 0x80000001 76 | $tpm2_flushcontext -t 77 | $tpm2_getcap handles-transient 78 | \end{verbatim} 79 | 80 | \subsection{Communicating with the TPM} 81 | If you are running against a real TPM, make sure you have access to the device. For example on Linux this means access to /dev/tpm0 and /dev/tpmrm0. In most distributions, and after installing the TPM2 Tools you will need to add your user to the tss group to get access to /dev/tpm0. 82 | 83 | If you are running against the TPM simulator, then it is likely you will need to set an environment variable to direct commands to the simulator. Set this \texttt{export TPM2TOOLS\_TCTI="mssim:host=localhost,port=2321"} 84 | 85 | You can run the simulator on a machine with a physical TPM too, just set the environment variable above to direct tpm2* commands to the correct place. 86 | 87 | \section{Exercises} 88 | Follow each of these in turn. Refer back to the tutorial section and your notes. 89 | 90 | \subsection{Generate Keys} 91 | Generate an RSA key under one of the hierarchies. I suggest creating a primary key in owner first and then deriving from that. 92 | 93 | Using this key encrypt a small amount of data, eg: 16 characters maximum. 94 | 95 | Decrypt that data and demonstrate that that the encrypt/decrypt works. 96 | 97 | \subsection{Generate and EK and AK} 98 | The EK is the device's identity in a way. Generate this. 99 | 100 | Then geneate an attestation key (AK). 101 | 102 | Make both of these persistent at suitable handles. 103 | 104 | \subsection{PCRs}\label{pcrs} 105 | List the PCRs and use \textit{tpm2\_pcrevent} to extend certain some PCRs. Pick some small files to hash with this command - hashing takes time and the TPM isn't a cryptoaccelerator! 106 | 107 | If you can reset the PCRs (something you can't do without a reboot in reality!), reset them and extend the PCRs using the same data but in different order. Compare what you get. 108 | 109 | 110 | \subsection{UEFI EventLog} 111 | \textbf{You must be running on a Linux machine with UEFI enabled} 112 | 113 | Read the UEFI eventlog which can be found at \textit{/sys/kernel/security/tpm0} using \textit{tmp2\_eventlog}. You will need to use sudo and write the output of the command to your home directory or somewhere suitable. Give this file a suitable name - you will need it later. Read it with a text editor. 114 | 115 | \begin{itemize} 116 | \item What does the event log tell you? 117 | \item How does it relate to the PCRs? 118 | \end{itemize} 119 | 120 | Reboot your machine and enter the UEFI setup page. If you can find something \textit{SAFE} to change, do it. If you are unsure, don't touch anything. Save and Exit and let the machine reboot. 121 | 122 | \begin{itemize} 123 | \item Read the event log again as above 124 | \item Compare it with the early event log you saved (you did this, yes?) 125 | \item What has changed 126 | \end{itemize} 127 | 128 | Did any PCRs? change - see section \ref{pcrs}. 129 | 130 | \subsection{Quotes} 131 | Take two quotes of your machine for the same PCRs. Use \textit{tpm2\_print} them. How do their differ? 132 | 133 | Suspend your machine, wake it up and take a quote, what has changed? 134 | 135 | Reboot your machine and take a quote, what has changed? 136 | 137 | \textbf{NB: this following exercise is dangeous and should not be attempted - disk corruption, breaking hardware etc. You have been warned} 138 | 139 | Remove the powersupply and pull the battery from your machine if you can. Reboot, take a quote and what does it tell you? 140 | 141 | \subsection{Updates} 142 | Linux has various ways of updating itself, eg: \textit{apt update/upgade, yum etc...} Take quotes, copies of the event log and PCRs \textit{BEFORE} the update. Reboot, and take quotes, eventlog and PCRs again. What has changed. 143 | 144 | Linux has a firmware update mechanism called LVFS and is used via the command \textit{fwupdmgr}. Take quotes, copies of the event log and PCRs \textit{BEFORE} the update. Reboot, and take quotes, eventlog and PCRs again. What has changed. 145 | 146 | 147 | 148 | 149 | 150 | \end{document} 151 | 152 | 153 | -------------------------------------------------------------------------------- /docs/Crim2023Tutorial/tutorial2023.toc: -------------------------------------------------------------------------------- 1 | \contentsline {section}{\numberline {1}Installation}{1}{}% 2 | \contentsline {section}{\numberline {2}Tutorial and TPM Familiarity}{2}{}% 3 | \contentsline {subsection}{\numberline {2.1}Basic Commands}{2}{}% 4 | \contentsline {subsection}{\numberline {2.2}Command Parameters}{2}{}% 5 | \contentsline {subsection}{\numberline {2.3}TPM Memory and Flush Context}{3}{}% 6 | \contentsline {subsection}{\numberline {2.4}Communicating with the TPM}{3}{}% 7 | \contentsline {section}{\numberline {3}Exercises}{3}{}% 8 | \contentsline {subsection}{\numberline {3.1}Generate Keys}{3}{}% 9 | \contentsline {subsection}{\numberline {3.2}Generate and EK and AK}{4}{}% 10 | \contentsline {subsection}{\numberline {3.3}PCRs}{4}{}% 11 | \contentsline {subsection}{\numberline {3.4}UEFI EventLog}{4}{}% 12 | \contentsline {subsection}{\numberline {3.5}Quotes}{5}{}% 13 | \contentsline {subsection}{\numberline {3.6}Updates}{5}{}% 14 | -------------------------------------------------------------------------------- /docs/STARTHERE.md: -------------------------------------------------------------------------------- 1 | # Getting started with TPM, or, *START HERE* 2 | 3 | Here you can find tutorials, examples and documentation on TPM functionality and different commands you can run. We use initially the tpm2-tools for Linux as the basis. 4 | 5 | These documents are meant to introduce basic concepts and commands that you can use on the TPM. 6 | 7 | The code examples included in these files can be tested with the simulator provided by the docker container available in this repository or you can test these against a real TPM. 8 | 9 | We also include information for the ELTT2 tool from Infineon - another useful tool for interacting with the TPM and one that will compile and run completely stand-alone wihtout any additional libraries on pretty much any Unix/Linux system. 10 | 11 | ## Contents 12 | 13 | While there is no strict order, if this is the first time you are here or you wish to work through in a proper methodological way then this is the order you should work through this course. 14 | 15 | * [Random](./random.md) covers the random number generator capabilities on the TPM. 16 | * [Objects](./objects.md) introduces the different kinds of objects you can store in a TPM and how to access and use them. 17 | * [Keys](./keys.md) contains an explanation of how the keys in the TPM work, as well as how to generate, load and use keys in the TPM. 18 | * [NVRAM](./nvram.md) explains how to use the TPM's Non-Volatile RAM as secure storage. 19 | * [PCRs](./pcrs.md) introduces the Platform configuration Registers (PCRs), which are used for storing measurements of a platform. 20 | * [Quoting](./quoting.md) covers the quoting mechanism, which is used to obtain measuremens from a TPM for remote attestation purposes. 21 | 22 | A Summary of all commands introduced is found in: 23 | 24 | * [Command Summary](./commandSummary.md) provides a summary of some of the TPM commands available and their posible use cases. 25 | 26 | A set of exercises for the above can be found here: 27 | 28 | * [Exercises](./exercises.md) exercises (surprisingly) 29 | 30 | 31 | ## ELTT2 32 | 33 | While the eltt2 code is not included in our container we have provided a short introduction to its operation. 34 | 35 | * [ELTT](./eltt2.md) covers basic usage of Infineon's eltt2 tool for embedded systems. Very useful for all devices! 36 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | [Start Here](./STARTHERE.md) 4 | 5 | # Contents 6 | 7 | - [Random](./random.md) 8 | - [Objects](./objects.md) 9 | - [Keys](./keys.md) 10 | - [Non-Volatile RAM](./nvram.md) 11 | - [Platform Configuration Registers](./pcrs.md) 12 | - [Quoting](./quoting.md) 13 | - [Command Summary](./commandSummary.md) 14 | - [Exercises](./exercises.md) 15 | -------------------------------------------------------------------------------- /docs/assets/ak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/ak.png -------------------------------------------------------------------------------- /docs/assets/create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/create.png -------------------------------------------------------------------------------- /docs/assets/createprimary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/createprimary.png -------------------------------------------------------------------------------- /docs/assets/ek.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/ek.png -------------------------------------------------------------------------------- /docs/assets/evictcontrol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/evictcontrol.png -------------------------------------------------------------------------------- /docs/assets/hierarchies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/hierarchies.png -------------------------------------------------------------------------------- /docs/assets/nvdefine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/nvdefine.png -------------------------------------------------------------------------------- /docs/assets/nvdefinepcrpolicy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/nvdefinepcrpolicy.png -------------------------------------------------------------------------------- /docs/assets/nvpcrpolicy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/nvpcrpolicy.png -------------------------------------------------------------------------------- /docs/assets/nvwrite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nokia/TPMCourse/a1dfe26d2daeba933d8df16b96737101274ab75b/docs/assets/nvwrite.png -------------------------------------------------------------------------------- /docs/commandSummary.md: -------------------------------------------------------------------------------- 1 | # Summary of Commands 2 | In this section we list the commands in the tutorial by use case. 3 | 4 | The TPM2 Tools commands all start with `tpm2_`. Other useful Linux command-line utilities and commands are also listed 5 | 6 | ## Random Numbers 7 | 8 | * tpm2_getrandom 9 | * tpm2_stirrandom 10 | 11 | ## TPM State and Objects 12 | 13 | * tpm2_getcap 14 | 15 | ## TPM Provisioning 16 | 17 | * tpm2_takeownership 18 | * tpm2_dictionarylockout 19 | 20 | * tpm2_clear 21 | 22 | * tpm2_changepps 23 | * tpm2_changeeps 24 | 25 | ## Key Management 26 | 27 | * tpm2_createprimary 28 | * tpm2_create 29 | * tpm2_load 30 | * tpm2_evictcontrol 31 | 32 | * tpm2_encrypt 33 | * tpm2_decrypt 34 | * tpm2_sign 35 | * tpm2_verify 36 | 37 | * tpm2_loadexternal 38 | * openssl 39 | 40 | ## NVRAM Management 41 | 42 | * tpm2_nvdefine 43 | * tpm2_nvwrite 44 | * tpm2_nvread 45 | * tpm2_nvundefine 46 | 47 | * tpm2_nvincrement 48 | 49 | * tpm2_writelock 50 | * tpm2_readlock 51 | 52 | * tpm2_createpolicy 53 | * tpm2_pcrread 54 | 55 | * sha256sum 56 | * sha1sum 57 | -------------------------------------------------------------------------------- /docs/eltt2.md: -------------------------------------------------------------------------------- 1 | # ELTT2 2 | 3 | Infineon make a small opensource tool for interacting with the TPM 2 device called $eltt2$. While not as sophisticated as the tpm2tools or the functionality provided by, say, the GO-TPM or WolfTPM libreries, it is very small, simple and can run on small embedded devices 4 | 5 | Eltt2 is primarily designed as a debugging tool, it should not be relied upon to provide attestation data etc. However it does run on practically anything (at least in our experience) :-) 6 | 7 | ## Help 8 | 9 | ```bash 10 | $eltt2 -h 11 | 12 | '-a ': Hash Sequence SHA-1 13 | -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...} 14 | '-A ': Hash Sequence SHA-256 15 | -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...} 16 | '-b ': Enter your own TPM command 17 | -> Command bytes: Enter your command bytes in hex like '0f56...' for {0x0f, 0x56, ...} 18 | '-c': Read Clock 19 | '-d ': Shutdown 20 | -> Shutdown types: clear [default], state 21 | '-e ': PCR Extend SHA-1 22 | -> PCR index: Enter the PCR index in hex like '17' for 0x17 23 | PCR digest: Enter the value to extend the PCR with in hex like '0f56...' for {0x0f, 0x56, ...} 24 | '-E ': PCR Extend SHA-256 25 | -> PCR index: Enter the PCR index in hex like '17' for 0x17 26 | PCR digest: Enter the value to extend the PCR with in hex like '0f56...' for {0x0f, 0x56, ...} 27 | '-g': Get fixed capability values 28 | '-v': Get variable capability values 29 | '-G ': Get Random 30 | -> Enter desired number of random bytes in hex like '20' for 0x20 (=32 bytes, maximum) 31 | '-h': Help 32 | '-r ': PCR Read SHA-1 33 | -> PCR index: Enter PCR number in hex like '17' for 0x17 34 | '-R ': PCR Read SHA-256 35 | -> PCR index: Enter PCR number in hex like '17' for 0x17 36 | '-s ': Hash SHA-1 37 | -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...} 38 | '-S ': Hash SHA-256 39 | -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...} 40 | '-t ': SelfTest 41 | -> Selftest type: not_full [default], full, incremental 42 | '-T': Get Test Result 43 | '-u ': Startup 44 | -> Startup types: clear [default], state 45 | '-z ': PCR Reset SHA-1 and SHA-256 46 | -> PCR index: Enter PCR number in hex like '17' for 0x17 47 | ``` 48 | 49 | Note, the examples here were run with `sudo` - this was because of the machine not being set up to allow access to the `/dev/tpm0` device by normal users. Typically the device is owned by the user and group `tss` and adding a normal user to this group will allow access without sudo. 50 | 51 | ## Random Numbres 52 | 53 | $ sudo ./eltt2 -G 10 54 | Random value: 55 | 56 | 0x00000000: 0xA5 0x36 0xB6 0xBF 0xA5 0x8B 0xD0 0x59 0x90 0xFD 0x1F 0x08 0x37 0x6A 0xF3 0xC9 57 | 58 | 59 | 60 | ## Hashing 61 | Eltt2 can hash suitablly presented data. The `-a` and `-s` options give access to the SHA-1 functions, while `-A` and `-S` to the SHA-256 functions. Eltt2 as you might notice is verbose, but then again it is more of a debugging and testing tool: 62 | 63 | ```bash 64 | ~/Work/eltt2$ sudo ./eltt2 -a abc 65 | 66 | 67 | TPM2_HashSequenceStart of 'abc' with SHA-1: 68 | TPM Response: 69 | 80 01 TPM TAG 70 | 00 00 00 0E RESPONSE SIZE 71 | 00 00 00 00 RETURN CODE 72 | Command-specific response Data: 73 | 80 00 00 00 74 | 75 | TPM2_SequenceUpdate: 76 | TPM Response: 77 | 80 02 TPM TAG 78 | 00 00 00 13 RESPONSE SIZE 79 | 00 00 00 00 RETURN CODE 80 | Command-specific response Data: 81 | 00 00 00 00 00 00 01 00 00 82 | 83 | TPM2_SequenceComplete: 84 | TPM Response: 85 | 80 02 TPM TAG 86 | 00 00 00 31 RESPONSE SIZE 87 | 00 00 00 00 RETURN CODE 88 | Command-specific response Data: 89 | 00 00 00 1E 00 14 DC AA 4E 54 90 | 32 32 BB B6 FD CB 68 D8 AC 4C 91 | 55 73 F3 6E 10 CA 80 24 40 00 92 | 00 07 00 00 00 00 01 00 00 93 | 94 | Hash value extracted from TPM response: 95 | 96 | 0x00000000: DC AA 4E 54 32 32 BB B6 97 | 0x00000008: FD CB 68 D8 AC 4C 55 73 98 | 0x00000010: F3 6E 10 CA 99 | 100 | 101 | ~/Work/eltt2$ sudo ./eltt2 -s abc 102 | 103 | 104 | TPM2_Hash of 'abc' with SHA-1: 105 | 106 | 0x00000000: DC AA 4E 54 32 32 BB B6 107 | 0x00000008: FD CB 68 D8 AC 4C 55 73 108 | 0x00000010: F3 6E 10 CA 109 | 110 | ``` 111 | 112 | 113 | ## Clock, Reset, Restart and Safe 114 | Eltt2 can read the TPM 2.0 clock status and provide information about the state of the device. For example, below we can see the uptime of the device, the time since the last TPM clear, the number of reboots (reset), the number of shutdowns - which actually refers to the number of *clean* shutdowns and whether the TPM was resarted from a properly shutdown state (safe): 115 | 116 | ```bash 117 | ~/Work/eltt2$ sudo ./eltt2 -c 118 | 119 | 120 | Clock info: 121 | ========================================================= 122 | Time since the last TPM_Init: 123 | 1934920 ms = 0 y, 0 d, 0 h, 32 min, 14 s, 920 ms 124 | 125 | Time during which the TPM has been powered: 126 | 35001929 ms = 0 y, 0 d, 9 h, 43 min, 21 s, 929 ms 127 | 128 | TPM Reset since the last TPM2_Clear: 12 129 | Number of times that TPM2_Shutdown: 1 130 | Safe: 1 = Yes 131 | 132 | ``` 133 | 134 | This same information is provided as part of the TPMS_ATTEST structure when quoting the TPM - see the tpm2tools tpm2_quote command. It can be used in the attestation process but be aware that the above information is provided as-is by the TPM and is not signed by the TPM. 135 | 136 | 137 | ## Reading and Writing the PCRs 138 | To read a PCR provide the PCR register in hexadecimal. The tool can only access the standard mandated SHA-1 and SHA-256 banks depending upon the commmand line option provided. The tool can only return a single PCR at a time so to obtain multiple PCR values, multiple individual calls must be made. 139 | 140 | ### Reading 141 | 142 | Accessing PCR 0 in the SHA-1 and SHA-256 banks is achieved respectively: 143 | 144 | ```bash 145 | ~/Work/eltt2$ sudo ./eltt2 -r 0 146 | 147 | Read PCR 0 (SHA-1): 148 | 20 E5 BB F9 0D 46 6A 79 75 7D 63 D9 94 B2 57 C9 02 F2 5F 9E 149 | 150 | ~/Work/eltt2$ sudo ./eltt2 -R 0 151 | 152 | Read PCR 0 (SHA-256): 153 | 79 86 0D C6 51 CE 87 C8 E4 F6 31 C5 FC ED D7 7B 0A 38 20 6A DE BC 14 4A 1B 8A 76 23 59 3E AA E2 154 | ``` 155 | 156 | Remeber hexadecimal: PCRs 10 to 23 ... dec 10 is hex A and dev 23 is hex 17, note the delberate errors below: 157 | 158 | ```bash 159 | ~/Work/eltt2$ sudo ./eltt2 -r a 160 | 161 | Read PCR 10 (SHA-1): 162 | 33 D1 BA C6 D2 AF 75 DC 95 55 B7 4E 0C 65 B1 35 27 FF D7 CE 163 | 164 | ~/Work/eltt2$ sudo ./eltt2 -r 17 165 | 166 | Read PCR 23 (SHA-1): 167 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 168 | 169 | ~/Work/eltt2$ sudo ./eltt2 -r 18 170 | 171 | Bad option. Enter a hex value between 0x00 and 0x17 in hex without leading '0x'. 172 | Unexpected error: 0xFFFFFFFE 173 | 174 | ~/Work/eltt2$ sudo ./eltt2 -r 23 175 | 176 | Bad option. Enter a hex value between 0x00 and 0x17 in hex without leading '0x'. 177 | Unexpected error: 0xFFFFFFFE 178 | ``` 179 | 180 | ### Extending 181 | 182 | Extending PCRs is similar straightforward with the correct size of digest being 0-padded. For example, extending PCR 23 )hex 17) with a digest starting with the bytes hex ABC... 183 | 184 | ```bash 185 | ~/Work/eltt2$ sudo ./eltt2 -e 17 abc 186 | 187 | Extend PCR 23 (SHA-1) with digest { AB 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 }: 188 | TPM Response: 189 | 80 02 TPM TAG 190 | 00 00 00 13 RESPONSE SIZE 191 | 00 00 00 00 RETURN CODE 192 | Command-specific response Data: 193 | 00 00 00 00 00 00 01 00 00 194 | 195 | ~/Work/eltt2$ sudo ./eltt2 -E 17 abc 196 | 197 | Extend PCR 23 (SHA-256) with digest { AB 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 }: 198 | TPM Response: 199 | 80 02 TPM TAG 200 | 00 00 00 13 RESPONSE SIZE 201 | 00 00 00 00 RETURN CODE 202 | Command-specific response Data: 203 | 00 00 00 00 00 00 01 00 00 204 | ``` 205 | 206 | 207 | ### Resetting 208 | 209 | Once the operating system is up and running and (at least on x86 devices) the TPM is running in locality 4. This means that only PCRs 16 and 23 (hex 10 and 17) are resettable (even when running as root!). 210 | 211 | We can reset PCR 23 with the `-z` option as demonstrated below: 212 | 213 | ```bash 214 | ~/Work/eltt2$ sudo ./eltt2 -r 17 215 | 216 | Read PCR 23 (SHA-1): 217 | 12 0B 50 96 72 A0 5D C9 2A AE F6 D9 91 73 56 22 FD 5C 95 2A 218 | 219 | ~/Work/eltt2$ sudo ./eltt2 -z 17 220 | 221 | Reset PCR 23 (SHA-1 and SHA-256): 222 | Done. 223 | 224 | 225 | ~/Work/eltt2$ sudo ./eltt2 -r 17 226 | 227 | Read PCR 23 (SHA-1): 228 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 229 | ``` 230 | 231 | 232 | Note: these examples are running in userland on Linux on an x86 machine. If you can run eltt at a different level, eg: as a firmware component, then you'll have much more opportunities to reset whatever you want. On other architectures and platforms, eg: embedded devices, ARM, RISC-V etc, the TPM may be in a different locality due to the design of that system. 233 | 234 | 235 | 236 | ## TPM Properties 237 | Finally the tool can prpvide information about the TPM itself 238 | 239 | ```bash 240 | ~/Work/eltt2$ sudo ./eltt2 -g 241 | 242 | 243 | TPM capability information of fixed properties: 244 | ========================================================= 245 | TPM_PT_FAMILY_INDICATOR: 2.0 246 | TPM_PT_LEVEL: 0 247 | TPM_PT_REVISION: 116 248 | TPM_PT_DAY_OF_YEAR: 15 249 | TPM_PT_YEAR: 2016 250 | TPM_PT_MANUFACTURER: STM 251 | TPM_PT_VENDOR_STRING: 252 | TPM_PT_VENDOR_TPM_TYPE: 1 253 | TPM_PT_FIRMWARE_VERSION: 71.12.40976.4 254 | 255 | TPM_PT_MEMORY: 256 | ========================================================= 257 | Shared RAM: 0 CLEAR 258 | Shared NV: 0 CLEAR 259 | Object Copied To Ram: 0 CLEAR 260 | 261 | TPM_PT_PERMANENT: 262 | ========================================================= 263 | Owner Auth Set: 0 CLEAR 264 | Sendorsement Auth Set: 0 CLEAR 265 | Lockout Auth Set: 0 CLEAR 266 | Disable Clear: 0 CLEAR 267 | In Lockout: 0 CLEAR 268 | TPM Generated EPS: 0 CLEAR 269 | 270 | 271 | ~/Work/eltt2$ sudo ./eltt2 -v 272 | 273 | 274 | TPM capability information of variable properties: 275 | 276 | TPM_PT_STARTUP_CLEAR: 277 | ========================================================= 278 | Ph Enable: 1 SET 279 | Sh Enable: 1 SET 280 | Eh Enable: 1 SET 281 | Orderly: 1 SET 282 | 283 | ``` 284 | 285 | 286 | -------------------------------------------------------------------------------- /docs/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | 3 | Some interesting exercises for you - this is incomplete but, let's see... 4 | 5 | ## Random Numbers 6 | 7 | 3 Simple exercises. Number #3 requires some bash/csh script programming. 8 | 9 | 1. Generate a single random value 10 | 2. What is the largest amount of random values your TPM can generate? 11 | 3. Write a small script that outputs a random value between, say 1 and 6. a TPM backed dice. 12 | 13 | ## Objects 14 | 15 | 1. What are the properties of your TPM? 16 | 2. Using `tpm2_getcap` find which PCR banks your TPM supports 17 | 3. What permanent objects are stored in the TPM? What are they exactly? 18 | 4. What cryptographic algorithms does your TPM support? 19 | 20 | 21 | ## PCRs 22 | 23 | 1. What do the PCRs on your machine report? 24 | 2. What do each of the PCRs mean? x86 UEFI machines and Linux/Windows, refer to the TCG documentation on this. Actually TianoCore's documentation has a good description of measured boot and what the PCRs mean - go find this. 25 | 3. Do any change after reboot? 26 | 4. Try entering the UEFI setup page and then letting the system boot...anything? 27 | 28 | ## Keys 29 | 30 | 1. Generate the PEM representations for the EK and AK - how would these be use to identify the TPM? 31 | 2. If you have access to two (or more) TPMs, generate your own keys on each, distribute the public keys and try sending encrypted messages between them, ie: encrypt on one TPM, decrypt on another... 32 | -------------------------------------------------------------------------------- /docs/gotpm.md: -------------------------------------------------------------------------------- 1 | # GO-TPM 2 | 3 | Go-TPM is a library written in Golang (or Go) for accessing TPM 2.0 (and 1.2) devices. The current state of the 1.2 libraries is limited so not all functionality is provided and the libraries are not being actively maintained. 4 | 5 | The TPM 2.0 libraries however are in good shape and relatively easy to use. It is important to note that that libraries conform to the TPM 2.0 specification and do not try to provide any convenience interfaces - this is a deliberate design decision - which means there are some surprises. 6 | 7 | Some familiarity with Go is expected here and not all functionality will be covered. The Go community and the Go-TPM team are pretty friendly however :-) 8 | 9 | ## Installation 10 | 11 | OK, I'm going to assume you have golang installed GOPATH set up and everything works...OK here'a test - save this as `helloworld.go`: 12 | 13 | ```go 14 | package main 15 | 16 | import "fmt" 17 | 18 | func main() { 19 | fmt.Println("Hello World") 20 | } 21 | ``` 22 | 23 | compile and run with 24 | 25 | ```bash 26 | go build helloworld.go 27 | ./helloworld 28 | ``` 29 | 30 | 31 | ## Go-TPM 32 | Found here: https://github.com/google/go-tpm 33 | 34 | "Go-TPM is a Go library that communicates directly with a TPM device on Linux or Windows machines." 35 | 36 | Unlike tpm2tools, GoTPM is a library for communicating with the TPM and supports both TPM 1.2 and 2.0 to some degree - actually TPM 1.2 is depreciated so YMMV. Most of the TPM 2.0 specification is supported. 37 | 38 | The library is also very faithful to the specification and provides little in the way of convenience functions. There are some caveats when using the library which need to worked around, but again this is due to the fact that it implements the specification! 39 | 40 | So, overall a very useful, functional library for accessing the TPM, but does require some knowledge of the TPM's workings. 41 | 42 | ## Some Sample Code 43 | In the following sections we show some annotated sample code. 44 | 45 | * gotpm_quote.md 46 | -------------------------------------------------------------------------------- /docs/gotpm_quote.md: -------------------------------------------------------------------------------- 1 | # GO-TPM Quote 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "flag" 8 | "fmt" 9 | "reflect" 10 | 11 | "github.com/google/go-tpm/tpm2" 12 | "github.com/google/go-tpm/tpmutil" 13 | ) 14 | 15 | 16 | var ( 17 | tpmPath = flag.String("tpm-path", "/dev/tpm0", "Path to the TPM device (character device or a Unix socket)") 18 | ) 19 | 20 | func main() { 21 | 22 | rwc, err := tpm2.OpenTPM(*tpmPath) 23 | if err != nil { 24 | fmt.Errorf("can't open TPM at %v", err) 25 | } 26 | //defer rwc.Close() 27 | 28 | //nonce := []byte{1, 2, 3, 4, 5, 6, 7, 8} 29 | 30 | var handle = tpmutil.Handle(0x81010006) 31 | 32 | fmt.Println("Handle is",handle) 33 | fmt.Println("Type:",reflect.TypeOf(handle).String()) 34 | 35 | // quote retuns 3 values, att, sig, err 36 | att, sig, err := tpm2.Quote( 37 | rwc, 38 | handle, 39 | "", 40 | "", 41 | nil, 42 | tpm2.PCRSelection{ tpm2.AlgSHA256 , []int{0} }, 43 | tpm2.AlgNull) 44 | 45 | if err != nil { 46 | fmt.Errorf("Problem getting quote %s", err) 47 | fmt.Println(err) 48 | } 49 | if sig != nil { 50 | fmt.Errorf("Sig is nil\n") 51 | } 52 | if att != nil { 53 | fmt.Errorf("Att is nil\n") 54 | } 55 | // att is of type []byte 56 | // sig is of type tpm2.Signature ?? 57 | // err is ?? 58 | fmt.Println("Err is *",err,"*") 59 | fmt.Println("length ",len(att)) 60 | fmt.Println("Att [% x] ",att) 61 | 62 | 63 | } 64 | ``` -------------------------------------------------------------------------------- /docs/keys.md: -------------------------------------------------------------------------------- 1 | # Keys 2 | - [Keys](#keys) 3 | - [Introduction](#introduction) 4 | - [Hierarchies and Use Cases](#hierarchies-and-use-cases) 5 | - [Creating A Hierarchy Primary Key](#creating-a-hierarchy-primary-key) 6 | - [Context Object](#context-object) 7 | - [Uniqueness of Primary Keys](#uniqueness-of-primary-keys) 8 | - [Creating Keys](#creating-keys) 9 | - [Persistence](#persistence) 10 | - [Reading the Public Part of a Key](#reading-the-public-part-of-a-key) 11 | - [Using Keys](#using-keys) 12 | - [Symmetric Encryption and Decryption](#symmetric-encryption-and-decryption) 13 | - [Software Encryption and Decryption](#software-encryption-and-decryption) 14 | - [Asymmetric Encryption and Decryption](#asymmetric-encryption-and-decryption) 15 | - [Signing and Verification](#signing-and-verification) 16 | - [Loading External Keys](#loading-external-keys) 17 | - [Loading an external public key](#loading-an-external-public-key) 18 | - [Loading external public and private keys](#loading-external-public-and-private-keys) 19 | - [Encrypting and Decrypting with External Objects](#encrypting-and-decrypting-with-external-objects) 20 | - [Special Keys](#special-keys) 21 | - [Endorsement key](#endorsement-key) 22 | - [Attestation key](#attestation-key) 23 | 24 | ## Introduction 25 | One of the major uses of the TPM is to generate, store and use encryption keys. 26 | In this respect the TPM behaves like a minature HSM. 27 | The TPM however is not designed as a crypto-accelerator and these operations are deliberately slow for security reasons. 28 | The TPM is designed to hide the private part of keys in such a way it can not be retrieved from the TPM. 29 | 30 | Note: in most of this section we use RSA public-private key pairs. Later on there are some examples using AES symmetric keys. 31 | 32 | Note: we show the output from the commands which includes information about the keys, the public key etc. Your output will differ as each key generated is unique. Only if the same seed is used in the key derivation functions will you see the same key being generated. As we are using a simulator this can actually be forced to happen - in a production environment or on a real device, this should never happen. 33 | 34 | ## TPM Memory 35 | TPMs have limited space for storing objects such as keys, session information etc. Different manufacturers provide different amounts of space and in some cases even behaviours when dealing with temporary objects. The IBM TPM Simulator used in the Dockerfiles has very limited storage and you'll find objects being left in the transient memory space. 36 | 37 | If you receive out of memory errors from the simulator or any TPM then check if there are objects (typically keys) in the transient memory area; for example we can use `tpm2_getcap` to display this and in this example we have two objects in the transient area. 38 | 39 | ```bash 40 | $tpm2_getcap handles-transient 41 | 0x80000000 42 | 0x80000001 43 | ``` 44 | 45 | To remove these objects use the command `tpm2_flushcontext -t` and check with `tpm2_getcap` again - if nothing is reported then all worked. 46 | 47 | ```bash 48 | $tpm2_getcap handles-transient 49 | 0x80000000 50 | 0x80000001 51 | $tpm2_flushcontext -t 52 | $tpm2_getcap handles-transient 53 | ``` 54 | 55 | Later on you'll see the command `tpm2_evictcontrol` which gives finer grained control over this. 56 | 57 | NOTE: normally temporary object are just temporary, but there are cases where and object is created here and is required by later operations in which case flushing the temporary area might have some other side-effects. This can be seen with certain credential and session auditing operations - these will be addressed later in this course and you don't have to worry about this for the time being. 58 | 59 | ## Hierarchies and Use Cases 60 | The TPM has four hierarchies. 61 | 62 | Three of the four hierarchies are used to provide the seeds and authorisation to create keys. 63 | 64 | A key can be made persistent in three of the hierarchies. The null hierarchy is a temporary area only. 65 | 66 | Hierarchies can be protected by passwords if set as described earlier. 67 | 68 | Three of the hierarchies are meant for different use cases and may be locked during a provisioning process. 69 | 70 | * *Platform* is used for use cases relating to the overall system, eg: manufacturer or OEM supplied keys 71 | * *Endorsement* is used for use case relating to keys used for signing, identity, attestation etc 72 | * *Owner* is used for use cases relating to any other use case - this one would be typically unlocked for use by applications 73 | 74 | The above are just guidelines - as far as the TPM is concerned, there are three hierarchies available for persistent storage and one for temporary. 75 | 76 | ![Hierachies](./assets/hierarchies.png "Hierarchies") 77 | 78 | ## Creating A Hierarchy Primary Key 79 | Each hierarchy has a seed from which a unique primary key for that hierarchy can be generated. 80 | The primary key is the root key for all keys generated thereafter and effectively links those keys in a key hierarchy. 81 | 82 | To create a primary key in the owner hierarchy: 83 | 84 | * `-C o` tells us to use the owner hierarchy 85 | * `-G rsa` tell us that we wish to generate an RSA key 86 | * `-g sha256` tell us that we wish to use the SHA256 hashing algorithm 87 | * `-c o.ctx` means to generate a TPM context object (called o.ctx) 88 | * `-a ` ... gives the attributes of the key - these will be explained later 89 | 90 | ```bash 91 | $ tpm2_createprimary -C o -g sha256 -G rsa -c o.ctx 92 | name-alg: 93 | value: sha256 94 | raw: 0xb 95 | attributes: 96 | value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|restricted|decrypt 97 | raw: 0x30072 98 | type: 99 | value: rsa 100 | raw: 0x1 101 | exponent: 0x0 102 | bits: 2048 103 | scheme: 104 | value: null 105 | raw: 0x10 106 | scheme-halg: 107 | value: (null) 108 | raw: 0x0 109 | sym-alg: 110 | value: aes 111 | raw: 0x6 112 | sym-mode: 113 | value: cfb 114 | raw: 0x43 115 | sym-keybits: 128 116 | rsa: daf0411d0000fb9a0cef9f24e512b2e8a6d4cbd288b8d39278853dd97b32c8d5247d757d7ced9148985c5ca0855038367f5fc91a15b168fdc3e7553d0ff59b851392b86c9667828576a3d3f0b1a9d5550df1251bee7969ca4c43403e024d97d1fd4fcdcfed9f8f5115e24450d24a5ea741e33594d99fda7fea3b2e799abb5131900fee62c8d6728da7e0aaa0351d5e9bcc59a5565d45fe6e942e7dfdd2ca22984bc0127a67a883ed58f7e872a96e148cf392f63ef1a36aeb54befa7918421eb0442a0ab86bd3d00d4b4e8a9145a8339ec138db0500b6f2260577e14fd2636fde4892c70b1a1d0bda44636eba9da7d8709c554a8c940473f3887287c257e91a01 117 | 118 | ``` 119 | 120 | ![CreatePrimary](./assets/createprimary.png "CreatePrimary") 121 | 122 | And the context object: 123 | 124 | ```bash 125 | $ ls -l o.ctx 126 | -rw-rw-r--. 1 fedora fedora 2332 Apr 8 14:30 o.ctx 127 | ``` 128 | 129 | ### Context Object 130 | The context object is a blob containing the key itself, that can only be used by the TPM that generated it. 131 | (NB: there is a way to make things portable, but later). 132 | 133 | Because TPM has limited storage capabilities, the context object keeps the information that would normally reside in the TPM and be accessable via a handle on disk instead. 134 | These are useful especially for primary keys, because storing these in a TPM would just take up space. 135 | Primary keys are always regenerable. 136 | 137 | ### Uniqueness of Primary Keys 138 | Each hierachy as mentioned as a seed and each time the primary key is generated it will be the same. We can easily demonstrate this. Let's generate two primary keys (using the ECC scheme): 139 | 140 | ```bash 141 | tpm2_createprimary -C o -g sha256 -G ecc -c unique1.ctx 142 | tpm2_createprimary -C o -g sha256 -G ecc -c unique2.ctx 143 | ``` 144 | 145 | The context object will differ at a binary level due to the internal naming of the keys. 146 | 147 | However, if we examine two specific properties of the keys, the ECC x and y parameters using `tpm2_readpublic` we can see that they are the same. 148 | The output here has been truncated to demonstrate this: 149 | 150 | ```bash 151 | diff unique1.ctx unique2.ctx 152 | Binary files unique1.ctx and unique2.ctx differ 153 | 154 | $ tpm2_readpublic -c unique1.ctx 155 | x: 83b84da5b14f618a54f5e3e988d14c448e8d04a463d56a235bf0c4a0c99f5209 156 | y: 2f8f5405f185d2077578f5861af011d0298a067471711ef24db4e7cf8ad5c382 157 | 158 | $ tpm2_readpublic -c unique2.ctx 159 | x: 83b84da5b14f618a54f5e3e988d14c448e8d04a463d56a235bf0c4a0c99f5209 160 | y: 2f8f5405f185d2077578f5861af011d0298a067471711ef24db4e7cf8ad5c382 161 | ``` 162 | 163 | Note, it is possible to change the seeds of the platform and endorsement hierarchies using the commands `tpm2_changepps` and `tpm2_changeeps`. These commands are not in the version of the tools supplied by the tutorial and not all TPMs necessarily support changing of these seeds. 164 | 165 | If the seed is changed the it will effectively sender the primary key for that hierarhcy and all keys under than hierarchy useless. You can figure out the potential for data loss yourselves. 166 | 167 | 168 | ## Creating Keys 169 | Now that we have a primary key created, we can generate actual, usable keys. 170 | 171 | First, we create a key. 172 | If no details are specified, the tools will default to an RSA key using SHA256 hashing an a set of default attributes. 173 | 174 | * `-C o.otx` - provides the parent object. In this case the context object of the primary key. We could specify a handle here. 175 | * `-u k1.pub` - the name of the file to which the public part of the key will be written 176 | * `-r k1.priv` - the name of the file to which the private part of the key will be written 177 | 178 | ```bash 179 | $ tpm2_create -C o.ctx -u k1.pub -r k1.priv 180 | name-alg: 181 | value: sha256 182 | raw: 0xb 183 | attributes: 184 | value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign 185 | raw: 0x60072 186 | type: 187 | value: rsa 188 | raw: 0x1 189 | exponent: 0x0 190 | bits: 2048 191 | scheme: 192 | value: null 193 | raw: 0x10 194 | scheme-halg: 195 | value: (null) 196 | raw: 0x0 197 | sym-alg: 198 | value: null 199 | raw: 0x10 200 | sym-mode: 201 | value: (null) 202 | raw: 0x0 203 | sym-keybits: 0 204 | rsa: de474081ed402efd9b4f531e55272f88affea88b8885467f9bbe91efe4e09f39bde20f06c52f3bca86136d1dfd6a5e0034c26bac3e96ea13adaf1bdb3971b1364352d9f662c8577b756f48c7069a6306c9b6dd689a2c37873c224ef9b9326c8ee3bb8d495cdb16677702ea4523baab41c5eb055b6bf9c67b6811e49f21b59a6d68a459ea4e1232f784827584a3afb31098fc523ad50cb7ee3d948d6e91373855f15cc0c6f635f5bbb4d998e6d001a1de3a7db09aa00e99e117f3dfd30db77db83f3dc8823e86087dbf9d9329918e4da753ee494426342099f401f508c7c2098ed0d7d0cb599055aff97f5761665e5393e1a2bd1c0219c335e8ada258271d310f 205 | 206 | ``` 207 | 208 | ![Create](./assets/create.png "Create") 209 | 210 | 211 | Now that the key has been generated, we can list the files. 212 | 213 | ```bash 214 | $ ls 215 | k1.priv k1.pub o.ctx 216 | ``` 217 | 218 | Now, we must load the key into the TPM to be able to use it. 219 | This process places the key into the transient part of the device. 220 | 221 | ```bash 222 | $ tpm2_load -C o.ctx -u k1.pub -r k1.priv -c k1.ctx 223 | name: 000b0fc7d55dacdf3cdd443a7724316b0bd0a90525f75aa8a809185c36584520630d 224 | ``` 225 | 226 | * `-C o.otx` - the parent key 227 | * `-u k1.pub` - the name of the file holding the public key 228 | * `-r k1.priv` - the name of the file holding the private key 229 | * `-c k1.ctx` - the context object for this key 230 | 231 | Once the key has been loaded, we can use it via its context object. 232 | 233 | ### Persistence 234 | If we wish to make the key persistent between restarts of the TPM, then we need to move the key from transient memory to persistent memory. 235 | 236 | ```bash 237 | $ tpm2_evictcontrol -C o -c k1.ctx 0x81010004 238 | persistent-handle: 0x81010004 239 | action: persisted 240 | ``` 241 | 242 | We can use `tpm2_getcap` to show the persistent handles: 243 | 244 | ```bash 245 | tpm2_getcap handles-persistent 246 | - 0x81010004 247 | ``` 248 | 249 | ![EvictControl](./assets/evictcontrol.png "EvictControl") 250 | 251 | If we try to place to object in the wrong hierarchy, we get an error: 252 | 253 | ```bash 254 | $ tpm2_evictcontrol -C p -c k1.ctx 0x81010004 255 | WARNING:esys:src/tss2-esys/api/Esys_EvictControl.c:326:Esys_EvictControl_Finish() Received TPM Error 256 | ERROR:esys:src/tss2-esys/api/Esys_EvictControl.c:114:Esys_EvictControl() Esys Finish ErrorCode (0x00000285) 257 | ERROR: Esys_EvictControl(0x285) - tpm:handle(2):hierarchy is not enabled or is not correct for the use 258 | ERROR:esys:src/tss2-esys/esys_tr.c:357:Esys_TR_Close() Error: Esys handle does not exist (70018). 259 | ERROR: Esys_TR_Close(0x1) - tpm:error(1.2): unknown version 1.2 error code 260 | ERROR: Unable to run tpm2_evictcontrol 261 | ``` 262 | 263 | To remove the key the process is such 264 | 265 | ```bash 266 | $ tpm2_evictcontrol -c 0x81010004 267 | $ tpm2_getcap handles-persistent 268 | ``` 269 | 270 | ### Reading the Public Part of a Key 271 | If we wish to examine a loaded object or a key persisted at some handle, we can output the details using `tpm2_readpublic`. 272 | 273 | ```bash 274 | $ tpm2_readpublic -c k1.ctx 275 | name: 000b0fc7d55dacdf3cdd443a7724316b0bd0a90525f75aa8a809185c36584520630d 276 | qualified name: 000b76956fbd30635aca249ddfc6949b80e8eace9d1f0e46c2b4cdbb2840e96f17c6 277 | name-alg: 278 | value: sha256 279 | raw: 0xb 280 | attributes: 281 | value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign 282 | raw: 0x60072 283 | type: 284 | value: rsa 285 | raw: 0x1 286 | exponent: 0x0 287 | bits: 2048 288 | scheme: 289 | value: null 290 | raw: 0x10 291 | scheme-halg: 292 | value: (null) 293 | raw: 0x0 294 | sym-alg: 295 | value: null 296 | raw: 0x10 297 | sym-mode: 298 | value: (null) 299 | raw: 0x0 300 | sym-keybits: 0 301 | rsa: ed357b6799949b22cacf76804017257a4649b8b8dcc209b9f41b4b630c7d98f1e909ed7d9dab897d031d344380f79eeec8acea027d3d8743b521483c3d0880b80a3c167a03358148c6d6017bb629fc2cb151662791717fe88bb35e1bd1f4e8b720326ec6d1ced62dba330b73b3dac04f44b62479f8aa6e2fdb01053b53b726ff051e91f09a1814bbfa1fbf3edd8cbde016d8c5727dd980723bdc6c9d806a1d89c17e928a980f8dccbf4c87a4ef590cd79819a5e6886644d1e9130d4bbb0b09631e3597edb4d670a9da66b9e06e0af5f7c2a891ab2fac44b578df0264a8a59aaf2a887b1c4dfb3274218577d9fe73b17db386cf25864a3e2868e97def64bd3019 302 | ``` 303 | 304 | The above is in the TSS format which isn't that useful. 305 | 306 | We can output in PEM format - usable by other tools such as openssl - like so: 307 | 308 | ```bash 309 | $ tpm2_readpublic -Q -c k1.ctx -f "pem" -o k1.pem 310 | $ cat k1.pem 311 | -----BEGIN PUBLIC KEY----- 312 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7TV7Z5mUmyLKz3aAQBcl 313 | ekZJuLjcwgm59BtLYwx9mPHpCe19nauJfQMdNEOA957uyKzqAn09h0O1IUg8PQiA 314 | uAo8FnoDNYFIxtYBe7Yp/CyxUWYnkXF/6IuzXhvR9Oi3IDJuxtHO1i26Mwtzs9rA 315 | T0S2JHn4qm4v2wEFO1O3Jv8FHpHwmhgUu/ofvz7djL3gFtjFcn3ZgHI73GydgGod 316 | icF+koqYD43Mv0yHpO9ZDNeYGaXmiGZE0ekTDUu7CwljHjWX7bTWcKnaZrngbgr1 317 | 98KokasvrES1eN8CZKilmq8qiHscTfsydCGFd9n+c7F9s4bPJYZKPiho6X3vZL0w 318 | GQIDAQAB 319 | -----END PUBLIC KEY----- 320 | ``` 321 | 322 | * `-f "pem"` --- format of the output 323 | * `-o filename` --- file into which the output is stored 324 | * `-Q` --- QUIET! This supresses the output to the console, useful for commands that generate huge amounts of console based output 325 | 326 | We can also output in the DER format. 327 | This time the output is in binary, hence the use of `hexdump`: 328 | 329 | ```bash 330 | $ tpm2_readpublic -Q -c k1.ctx -f "der" -o k1.der 331 | $ cat k1.der | hexdump 332 | 0000000 8230 2201 0d30 0906 862a 8648 0df7 0101 333 | 0000010 0501 0300 0182 000f 8230 0a01 8202 0101 334 | 0000020 ed00 7b35 9967 9b94 ca22 76cf 4080 2517 335 | 0000030 467a b849 dcb8 09c2 f4b9 4b1b 0c63 987d 336 | 0000040 e9f1 ed09 9d7d 89ab 037d 341d 8043 9ef7 337 | 0000050 c8ee eaac 7d02 873d b543 4821 3d3c 8008 338 | 0000060 0ab8 163c 037a 8135 c648 01d6 b67b fc29 339 | 0000070 b12c 6651 9127 7f71 8be8 5eb3 d11b e8f4 340 | 0000080 20b7 6e32 d1c6 d6ce ba2d 0b33 b373 c0da 341 | 0000090 444f 24b6 f879 6eaa db2f 0501 533b 26b7 342 | 00000a0 05ff 911e 9af0 1418 fabb bf1f dd3e bd8c 343 | 00000b0 16e0 c5d8 7d72 80d9 3b72 6cdc 809d 1d6a 344 | 00000c0 c189 927e 988a 8d0f bfcc 874c efa4 0c59 345 | 00000d0 98d7 a519 88e6 4466 e9d1 0d13 bb4b 090b 346 | 00000e0 1e63 9735 b4ed 70d6 daa9 b966 6ee0 f50a 347 | 00000f0 c2f7 91a8 2fab 44ac 78b5 02df a864 9aa5 348 | 0000100 2aaf 7b88 4d1c 32fb 2174 7785 fed9 b173 349 | 0000110 b37d cf86 8625 3e4a 6828 7de9 64ef 30bd 350 | 0000120 0219 0103 0100 351 | 0000126 352 | ``` 353 | 354 | Finally, using `openssl`, we can examine the outputs from above, for example the PEM file: 355 | 356 | ```bash 357 | $ openssl rsa -pubin -inform "pem" -text -in k1.pem 358 | RSA Public-Key: (2048 bit) 359 | Modulus: 360 | 00:ed:35:7b:67:99:94:9b:22:ca:cf:76:80:40:17: 361 | 25:7a:46:49:b8:b8:dc:c2:09:b9:f4:1b:4b:63:0c: 362 | 7d:98:f1:e9:09:ed:7d:9d:ab:89:7d:03:1d:34:43: 363 | 80:f7:9e:ee:c8:ac:ea:02:7d:3d:87:43:b5:21:48: 364 | 3c:3d:08:80:b8:0a:3c:16:7a:03:35:81:48:c6:d6: 365 | 01:7b:b6:29:fc:2c:b1:51:66:27:91:71:7f:e8:8b: 366 | b3:5e:1b:d1:f4:e8:b7:20:32:6e:c6:d1:ce:d6:2d: 367 | ba:33:0b:73:b3:da:c0:4f:44:b6:24:79:f8:aa:6e: 368 | 2f:db:01:05:3b:53:b7:26:ff:05:1e:91:f0:9a:18: 369 | 14:bb:fa:1f:bf:3e:dd:8c:bd:e0:16:d8:c5:72:7d: 370 | d9:80:72:3b:dc:6c:9d:80:6a:1d:89:c1:7e:92:8a: 371 | 98:0f:8d:cc:bf:4c:87:a4:ef:59:0c:d7:98:19:a5: 372 | e6:88:66:44:d1:e9:13:0d:4b:bb:0b:09:63:1e:35: 373 | 97:ed:b4:d6:70:a9:da:66:b9:e0:6e:0a:f5:f7:c2: 374 | a8:91:ab:2f:ac:44:b5:78:df:02:64:a8:a5:9a:af: 375 | 2a:88:7b:1c:4d:fb:32:74:21:85:77:d9:fe:73:b1: 376 | 7d:b3:86:cf:25:86:4a:3e:28:68:e9:7d:ef:64:bd: 377 | 30:19 378 | Exponent: 65537 (0x10001) 379 | writing RSA key 380 | -----BEGIN PUBLIC KEY----- 381 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7TV7Z5mUmyLKz3aAQBcl 382 | ekZJuLjcwgm59BtLYwx9mPHpCe19nauJfQMdNEOA957uyKzqAn09h0O1IUg8PQiA 383 | uAo8FnoDNYFIxtYBe7Yp/CyxUWYnkXF/6IuzXhvR9Oi3IDJuxtHO1i26Mwtzs9rA 384 | T0S2JHn4qm4v2wEFO1O3Jv8FHpHwmhgUu/ofvz7djL3gFtjFcn3ZgHI73GydgGod 385 | icF+koqYD43Mv0yHpO9ZDNeYGaXmiGZE0ekTDUu7CwljHjWX7bTWcKnaZrngbgr1 386 | 98KokasvrES1eN8CZKilmq8qiHscTfsydCGFd9n+c7F9s4bPJYZKPiho6X3vZL0w 387 | GQIDAQAB 388 | -----END PUBLIC KEY----- 389 | ``` 390 | 391 | All of the above can be accomplised by referring to a handle in the TPM rather than a context object. 392 | 393 | We reload the context object, read the public portion and write it out to a file, compare this file with the earlier output from the context object and then evict the object from the TPM. 394 | 395 | ```bash 396 | $ tpm2_evictcontrol -C o -c k1.ctx 0x81010004 397 | persistent-handle: 0x81010004 398 | action: persisted 399 | $ tpm2_readpublic -Q -c 0x81010004 -f "pem" -o k1handle.pem 400 | $ cat k1handle.pem 401 | -----BEGIN PUBLIC KEY----- 402 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxX5NWO4PGGa9jjAH/6oa 403 | OM7DuNhQAoPMeX7WzLUlsv8Ck8/tO4TldrlWcgtDGREyCxl+6A735/P7Om6w5N90 404 | 9e3G+s5O8clQqC/j8HOGZ1qppS9FCMcXhO4WwIx/yWOAR1amyPCMbQCVZucZOp/n 405 | B19I04rb1zMCxUqiALSyFLLiTbNlpe7VwbCswt/7TCnZ1HU3NfQnKqxxWzW06C60 406 | ixl3bGlUB3QQJwkUgEyJZlCh6MDkTQqOiVaQs7OZvk7nP2+l3YZUCqjqLt6gSy2Q 407 | i2BEzDY+qJPHGV7pXC1LuLgAwOIANSUeFBzXc0AacKuHEhRwuu6mCHbCVll5AC+C 408 | lQIDAQAB 409 | -----END PUBLIC KEY----- 410 | $ diff k1handle.pem k1.pem 411 | $ tpm2_evictcontrol -c 0x81010004 412 | persistent-handle: 0x81010004 413 | action: evicted 414 | ``` 415 | 416 | Note: Keep the file `o.ctx` around, we will use it in the next sections. 417 | 418 | ## Using Keys 419 | In this section, we show the four basic operations related to keys. 420 | 421 | * Encryption 422 | * Decryption 423 | * Signing 424 | * Verification 425 | 426 | First, we will create a primary key under the owner hierarchy and a new RSA key under that. 427 | We will store both keys in the handles given in the example below. 428 | After this exercise both keys can be removed. 429 | 430 | We will use the `o.ctx` file that we created in the [Primary Key](#primary-key) section. 431 | This context file contains the primary key we generated in the owner hierarchy. 432 | 433 | The TPM 2.0 standard provides for at least three key families: 434 | 435 | * RSA 436 | * ECC 437 | * AES 438 | 439 | We'll demonstrate both symmetric and assymmetric schemes below. 440 | Their operations are similar but the commands used have different namings. 441 | 442 | ### Symmetric Encryption and Decryption 443 | First, we create an AES key: 444 | 445 | ```bash 446 | tpm2_create -C o.ctx -g sha256 -G aes -u mysymmetrickey.pub -r mysymmetrickey.priv 447 | tpm2_load -C o.ctx -u mysymmetrickey.pub -r mysymmetrickey.priv -c mysymmetrickey.ctx 448 | tpm2_evictcontrol -C o -c mysymmetrickey.ctx 0x81010020 449 | ``` 450 | 451 | Note: yes, it looks really odd that a symmetric key has a public and private part. 452 | The actual symmetric key here is stored in the file `mysymmetrickey.priv`. 453 | 454 | When you generate a symmetric key you can optionally output the public object, but that is not a public object in the terms of public key crypto but instead a public object in TPM terms. 455 | Meaning that this object (`mysymmetrickey.pub`) contains metadata about the AES key you created and the actual key is in `mysymmetrickey.priv` in this example. 456 | 457 | Now, we have our key persisted in the handle `0x81010020`. 458 | 459 | ```bash 460 | $ echo "My Password" > mysecret 461 | $ tpm2_encryptdecrypt -c 0x81010020 -o mysecret.enc mysecret 462 | WARN: Using a weak IV, try specifying an IV 463 | $ cat mysecret.enc | hexdump 464 | 0000000 9736 1b07 0152 f14f ade4 5846 465 | 000000c 466 | ``` 467 | 468 | The weak IV error relates to the initialisation vector used by the AES algorithm. 469 | The tools are warning us that without an initialisation vector, the encryption is weak and prone to relatively easy attack. 470 | 471 | Decryption is done similarly to encryption (except in reverse) using the `-d` option. 472 | 473 | ```bash 474 | $ tpm2_encryptdecrypt -d -c 0x81010020 -o mysecret.dec mysecret.enc 475 | WARN: Using a weak IV, try specifying an IV 476 | ``` 477 | 478 | We can also check that the encryption and decryption actually took place. 479 | 480 | ```bash 481 | $ ls -l mysecret* 482 | -rw-rw-r--. 1 fedora fedora 12 Apr 15 19:36 mysecret 483 | -rw-rw-r--. 1 fedora fedora 12 Apr 15 19:42 mysecret.dec 484 | -rw-rw-r--. 1 fedora fedora 12 Apr 15 19:36 mysecret.enc 485 | $ diff mysecret mysecret.dec 486 | $ cmp mysecret mysecret.dec 487 | $ cat mysecret 488 | My Password 489 | $ cat mysecret.dec 490 | My Password 491 | $ cat mysecret.enc | hexdump 492 | 0000000 8623 6c6c 17f3 8530 6868 1745 493 | 000000c 494 | ``` 495 | 496 | ### Software Encryption and Decryption 497 | 498 | Not all TPMs will support the functionality provided by tpm2_encryptdecrypt (an optional part of the TPM specification). 499 | 500 | In these instances you can use the TPM to seal a key, then pass it into an external library (such as OpenSSL) to handle the encryption and decryption process instead. 501 | 502 | We can use the TPM's random number generator to create a 256 bit symetric key for our crypto library. 503 | 504 | ```bash 505 | $ tpm2_getrandom 32 > symmetrickey.key 506 | ``` 507 | *It's worth noting here that a real implementation should never write an unencrypted key to disk. Instead it should be processed in a trusted environment and erased when no longer required.* 508 | 509 | We need to seal this key using the TPM. As with previous examples, the library will return a public and private key pair that can be used to retrieve the data later. 510 | 511 | ```bash 512 | $ tpm2_create -C o.ctx -i symmetrickey.key -u key.pub -r key.priv 513 | ``` 514 | 515 | *In addition to sealing the key against the TPM, platform configuration registers can also be used to increase security here. See [PCRs](./pcrs.md).* 516 | 517 | To access the key and encrypt/decrypt your files, load the public and private key into the TPM and unseal the data. The unsealing operation should only be performed in a trusted environment, as it again exposes the plaintext symmetric key. 518 | 519 | ```bash 520 | $ tpm2_load -C o.ctx -u key.pub -r key.priv -c key.ctx 521 | $ tpm2_unseal -c key.ctx > unsealedsymmetrickey.key 522 | ``` 523 | Encryption/decryption can now be performed using your preferred crypto library and the unsealed key. 524 | 525 | ### Asymmetric Encryption and Decryption 526 | We can also use the TPM to do asymmetric encyption and decryption. 527 | This uses specific commands for RSA encryption and decryption. 528 | 529 | ```bash 530 | tpm2_create -C o.ctx -g sha256 -G rsa -u myasymmetrickey.pub -r myasymmetrickey.priv 531 | tpm2_load -C o.ctx -u myasymmetrickey.pub -r myasymmetrickey.priv -c myasymmetrickey.ctx 532 | tpm2_evictcontrol -C o -c myasymmetrickey.ctx 0x81010021 533 | ``` 534 | 535 | Now, we have our key persisted in the handle `0x81010021`. 536 | 537 | As before, we will encrypt our secret password: 538 | 539 | ```bash 540 | $ echo "My Password" > mysecret 541 | $ tpm2_rsaencrypt -c 0x81010021 -o mysecret.enc2 mysecret 542 | $ cat mysecret.enc2 | hexdump 543 | 0000000 1bc2 cf8f 43bf 695f d6d8 b97b 22d8 4fd0 544 | 0000010 649f 6b3b f7e9 1081 fba0 7d31 88c8 085d 545 | 0000020 2db8 faec b43a d7ec 1ea1 20a0 6f09 c0cc 546 | 0000030 f9a8 c47f f5c6 8360 7156 615e 0fc2 7721 547 | 0000040 7c50 ba4d 0712 6393 8e28 1204 c2b7 e377 548 | 0000050 d826 14b2 9260 9ba2 98b3 ddf8 6cdc 1aeb 549 | 0000060 bf93 1427 da85 24c2 4c07 e48e 1c7c 540f 550 | 0000070 df86 8b68 717a a4d7 a073 ea70 f160 c445 551 | 0000080 0c6c 43ca 8206 da4a 2048 af5f 93d1 3216 552 | 0000090 051b 9857 5034 dbfc 880a 5df2 e79f 6136 553 | 00000a0 10e7 08c7 32f2 aed3 b3cd a1da c7e2 3a67 554 | 00000b0 c3e2 f6c0 a639 9637 edc1 3806 9784 f308 555 | 00000c0 e939 fc6b a0f4 b184 ad81 af01 d7e7 e7cc 556 | 00000d0 0ed2 a4d0 342d af60 2a20 fab9 3633 689b 557 | 00000e0 8cd6 4821 308f 8505 4a4b 7423 5e35 18bc 558 | 00000f0 76c0 f3e8 a3db 468c 50b1 2008 274a 489c 559 | 0000100 560 | ``` 561 | 562 | RSA decryption has its own command: 563 | 564 | ```bash 565 | $ tpm2_rsadecrypt -c 0x81010021 -o mysecret.dec2 mysecret.enc2 566 | $ cat mysecret.dec2 567 | My Password 568 | ``` 569 | 570 | Keep these keys in the TPM - don't evict them yet, we'll reuse them in the next section on signing 571 | 572 | ### Signing and Verification 573 | We can cryptographically sign a message using the `tpm2_sign` command with the following options: 574 | 575 | * `-c` is the context object or handle of the signing key 576 | * `-g` is the hash algorithm used 577 | * `-o` is the output file into which the signature is written 578 | 579 | Let's make our message a novel: 580 | 581 | ```bash 582 | $ echo "Once upon a time..." > myGreatNovel.txt 583 | $ tpm2_sign -c 0x81010021 -g sha256 -o myGreatNovel.sig myGreatNovel.txt 584 | $ cat myGreatNovel.sig | hexdump 585 | 0000000 1400 0b00 0001 5b59 2ee7 c816 891d 0897 586 | 0000010 9475 eb54 1dec f155 c2c0 f01d b6a5 0fd9 587 | 0000020 064a 8f00 5272 e1de 3cbf 9a6a 2367 5681 588 | 0000030 91d4 e68a d648 1e99 4513 aea8 79e7 07b4 589 | 0000040 a9f6 ba43 fe04 f181 b68a ae93 56bc d02b 590 | 0000050 0bf9 de77 1ca0 4019 328d 9bdb cdd0 5abd 591 | 0000060 3235 155d 3ca2 a8f2 fa90 12b0 101f 8577 592 | 0000070 0c2d 13a8 73c6 8cae 8437 7432 faf1 98df 593 | 0000080 8452 16e6 63b0 e9e3 0f05 c25b c202 ca8f 594 | 0000090 6b18 5c09 a504 799e d42d 506a 3c2d 9427 595 | 00000a0 474b 9f5e f2f2 8d3f cdb9 af9a 44a0 12ee 596 | 00000b0 cdba 81f1 75a3 ab13 8d78 dbc4 78ca 8614 597 | 00000c0 7ef1 4962 888c e15b f6aa 1b6f 8631 d4d9 598 | 00000d0 333b a90f efe1 236f 9d1d 54ac ebe4 8747 599 | 00000e0 6452 b7e4 7272 e4b9 f72e 9820 e3cb 2a86 600 | 00000f0 d0e6 0aec e9e6 d0e9 1325 8d63 543b c806 601 | 0000100 a0cb 7722 23ba 602 | 0000106 603 | ``` 604 | 605 | and to ensure that the novel has not been tampered with, we can verify it against the signature: 606 | 607 | ```bash 608 | $ tpm2_verifysignature -c 0x81010021 -g sha256 -s myGreatNovel.sig -m myGreatNovel.txt 609 | $ echo $? 610 | 0 611 | ``` 612 | * `-c` is the context object or handle of the signing key 613 | * `-g` the hash algorithm to use 614 | * `-s` the signature file 615 | * `-m` the original file to check against 616 | 617 | The `tpm2_verifysignature` command does not produce any output if successful. 618 | It just returns code `0` back to the shell. 619 | 620 | However, if the file has been tampered with: 621 | 622 | ```bash 623 | $ echo "tampered" >> myGreatNovel.txt 624 | $ tpm2_verifysignature -c 0x81010021 -g sha256 -s myGreatNovel.sig -m myGreatNovel.txt 625 | WARNING:esys:src/tss2-esys/api/Esys_VerifySignature.c:302:Esys_VerifySignature_Finish() Received TPM Error 626 | ERROR:esys:src/tss2-esys/api/Esys_VerifySignature.c:103:Esys_VerifySignature() Esys Finish ErrorCode (0x000002db) 627 | ERROR: Esys_VerifySignature(0x2DB) - tpm:parameter(2):the signature is not valid 628 | ERROR: Verify signature failed! 629 | ERROR: Unable to run tpm2_verifysignature 630 | $ echo $? 631 | 1 632 | ``` 633 | 634 | We get an error on `stderr` and the return code `1` back to the shell. 635 | In fact, this how all the `tpm2_*` tools work, but as explained earlier in this tutorial we output everything. 636 | 637 | 638 | ## Loading External Keys 639 | While the TPM can generate keys, it is often the case that keys will be generated externally. 640 | The `tpm2_loadexternal` command functions similarly to the `tpm2_load` command introduced earlier. 641 | 642 | ### Loading an external public key 643 | A typical scenario is one where you have been supplied a public key by someone. 644 | The other party will have generated a public-private key pair using some mechanism, eg: a TPM or using `openssl`: 645 | 646 | ```bash 647 | $ openssl genrsa -out private.pem 2048 648 | Generating RSA private key, 2048 bit long modulus (2 primes) 649 | ...........................................+++++ 650 | ....+++++ 651 | e is 65537 (0x010001) 652 | $ openssl rsa -in private.pem -out public.pem -outform PEM -pubout 653 | writing RSA key 654 | $ ls private.pem public.pem 655 | private.pem public.pem 656 | $ ls -l private.pem public.pem 657 | -rw-------. 1 fedora fedora 1675 Apr 20 15:35 private.pem 658 | -rw-rw-r--. 1 fedora fedora 451 Apr 20 15:35 public.pem 659 | ``` 660 | 661 | Whoever created the above might then send you their `public.pem` key, and you can load it into the TPM with the following command: 662 | 663 | ```bash 664 | $ tpm2_loadexternal -C o -G rsa -u public.pem -c external1.ctx 665 | name: 000b6475122adb0640594f51ebeba6de0580f061542fb53cb86d99e6fe70763fa76a 666 | ``` 667 | 668 | The context object is then used to access the key. 669 | 670 | We can read the properties of this key as before: 671 | 672 | ```bash 673 | $ tpm2_readpublic -c external1.ctx -f "pem" -o external1rp.pem 674 | name: 000b6475122adb0640594f51ebeba6de0580f061542fb53cb86d99e6fe70763fa76a 675 | qualified name: 000b6475122adb0640594f51ebeba6de0580f061542fb53cb86d99e6fe70763fa76a 676 | name-alg: 677 | value: sha256 678 | raw: 0xb 679 | attributes: 680 | value: userwithauth|decrypt|sign 681 | raw: 0x60040 682 | type: 683 | value: rsa 684 | raw: 0x1 685 | exponent: 0x10001 686 | bits: 2048 687 | scheme: 688 | value: null 689 | raw: 0x10 690 | scheme-halg: 691 | value: (null) 692 | raw: 0x0 693 | sym-alg: 694 | value: null 695 | raw: 0x10 696 | sym-mode: 697 | value: (null) 698 | raw: 0x0 699 | sym-keybits: 0 700 | rsa: cab24fb663e504e3bcc5850017bec06e19d9059f540335c9c367f99990469092555c60030543bfb72ae5e02b043643eb95c9256821f1dce1056bfeaa396f0fb18011090703e38bb49fc2fde9c05b4efe77e16bc694497a313ab1680f23912321fbc75dbd57d368e73bdf73493f199199e3b7df4a81afae65b87d3a0ce448daadad8f39fb2d6524c76a2f46e90f2e49af7cb701a18a1f8d9c0519ead9be130ef6b22129b72bfa14648d875cea640cffbd1c7ef79b8f2fd2cc331617bd604c839eb4cc876ab01ba1d7747d4dcb427b5e36795f3fea882ede4447c80e8ee91e3103858d6bba86e2e18e3816c33f36833a452d14d19e22ae60bbe6e288bb05cf911b 701 | ``` 702 | 703 | And, if we compare what `openssl` generated against what we read from the TPM, it will not be a surprise that they are the same: 704 | 705 | ```bash 706 | $ diff public.pem external1rp.pem 707 | $ cat public.pem 708 | -----BEGIN PUBLIC KEY----- 709 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyrJPtmPlBOO8xYUAF77A 710 | bhnZBZ9UAzXJw2f5mZBGkJJVXGADBUO/tyrl4CsENkPrlcklaCHx3OEFa/6qOW8P 711 | sYARCQcD44u0n8L96cBbTv534WvGlEl6MTqxaA8jkSMh+8ddvVfTaOc733NJPxmR 712 | meO330qBr65luH06DORI2q2tjzn7LWUkx2ovRukPLkmvfLcBoYofjZwFGerZvhMO 713 | 9rIhKbcr+hRkjYdc6mQM/70cfvebjy/SzDMWF71gTIOetMyHarAbodd0fU3LQnte 714 | NnlfP+qILt5ER8gOjukeMQOFjWu6huLhjjgWwz82gzpFLRTRniKuYLvm4oi7Bc+R 715 | GwIDAQAB 716 | -----END PUBLIC KEY----- 717 | $ cat external1rp.pem 718 | -----BEGIN PUBLIC KEY----- 719 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyrJPtmPlBOO8xYUAF77A 720 | bhnZBZ9UAzXJw2f5mZBGkJJVXGADBUO/tyrl4CsENkPrlcklaCHx3OEFa/6qOW8P 721 | sYARCQcD44u0n8L96cBbTv534WvGlEl6MTqxaA8jkSMh+8ddvVfTaOc733NJPxmR 722 | meO330qBr65luH06DORI2q2tjzn7LWUkx2ovRukPLkmvfLcBoYofjZwFGerZvhMO 723 | 9rIhKbcr+hRkjYdc6mQM/70cfvebjy/SzDMWF71gTIOetMyHarAbodd0fU3LQnte 724 | NnlfP+qILt5ER8gOjukeMQOFjWu6huLhjjgWwz82gzpFLRTRniKuYLvm4oi7Bc+R 725 | GwIDAQAB 726 | -----END PUBLIC KEY----- 727 | ``` 728 | 729 | External keys can not be made persistent so `tpm2_evictcontrol` will not work. 730 | 731 | ### Loading external public and private keys 732 | The process for loading both the public and private keys is similar. 733 | Using the keys we generated ealier, we can load the private key into the *null* hierarchy. 734 | Attempting to load a key into the owner or platform hierarchies will result in a failure. 735 | 736 | ```bash 737 | $ tpm2_loadexternal -C n -G rsa -r private.pem -c external2.ctx 738 | name: 000b3acc07d18ee1d8d335959ff9f21f3281e82c879db0c3389efdc5789a385990b9 739 | ``` 740 | 741 | ### Encrypting and Decrypting with External Objects 742 | First, Alice creates a key pair called Alice. 743 | 744 | ```bash 745 | $ openssl genrsa -out aliceprivate.pem 2048 746 | Generating RSA private key, 2048 bit long modulus (2 primes) 747 | ...........+++++ 748 | ....................................+++++ 749 | e is 65537 (0x010001) 750 | $ openssl rsa -in aliceprivate.pem -out alicepublic.pem -outform PEM -pubout 751 | writing RSA key 752 | ``` 753 | 754 | Alice sends Bob her public key and he sends back a secret message, which is encrypted with Alice's public key. 755 | 756 | ```bash 757 | $ echo "Secret message" > secretmessage.txt 758 | $ openssl rsautl -encrypt -inkey alicepublic.pem -pubin -in secretmessage.txt -out secretmessage.enc 759 | $ cat secretmessage.enc | hexdump 760 | 0000000 7933 31fc c2ba e703 4a51 7552 1750 1db7 761 | 0000010 35f7 092c 42be 7a3f f976 8e56 1f3a ef69 762 | 0000020 995e a6b1 0a0f 1cde 774b 7c57 9f4b 4cce 763 | 0000030 2692 94d3 fca8 c0bd c0a9 7baa 3678 9d7a 764 | 0000040 74bd e115 736d aa58 be70 54ac a39a ca24 765 | 0000050 d50a b6d1 0f88 4838 f2ab e130 1755 c84a 766 | 0000060 ebe8 adf9 e459 516b b113 96ed d815 bd38 767 | 0000070 849e f456 93f7 ec64 4eaa 8f37 f5dd b8cc 768 | 0000080 c856 00cf db98 361e 5405 82fb 7eaf 9e99 769 | 0000090 7346 e610 e913 8fb7 5490 0c4f 033b 5146 770 | 00000a0 b810 f92c 1537 0110 5773 2739 4266 50cc 771 | 00000b0 aaf0 ca8b c8a1 9da5 6da4 5f53 8d8f f5ca 772 | 00000c0 688c 49d1 4cb9 4e0d e1e6 e5dc d0c2 6e3a 773 | 00000d0 88ae a11f ef2b 33c3 1a4b 069b 34cb 8417 774 | 00000e0 23ce 3474 62e6 cd0e 0199 00b9 79e1 c514 775 | 00000f0 e3d9 d334 467d ea97 c3fb 826a 3beb 7b67 776 | ``` 777 | 778 | Alice has now received the secret message from Bob, that only she can decrypt by using the private part of her key pair. 779 | So, she loads her private key into her TPM and uses it to decrypt the message from Bob. 780 | 781 | ```bash 782 | $ tpm2_loadexternal -G rsa -C n -r aliceprivate.pem -c alice.ctx 783 | name: 000bc6bce3a1ec9182e51e25dbb4a2e2af66ceb33806d32ffbb261a40851cf26c14d 784 | $ tpm2_rsadecrypt -c alice.ctx -o secretmessage.dec secretmessage.enc 785 | $ cat secretmessage.dec 786 | Secret message 787 | ``` 788 | 789 | Alice is now happy. 790 | 791 | A similar procedure can be done using Alice's private key and Bob decrypting it with Alice's public key. 792 | 793 | Also, as an exercise, try doing this with AES symmetric keys (hint: use `tpm2_encryptdecrypt`). 794 | 795 | ## Special Keys 796 | We can generate two public/private key pairs from the unique seed burned into each TPM chip that is manufactured: an Endorsement Key (EK) and an Attestation Key (AK). 797 | 798 | The EK is a restricted key for encryption/decryption and the AK is a restricted key for signing. 799 | *Restricted* means that these keys can only encrypt/decrypt/sign objects inside the TPM itself. 800 | The private part of the keys can never be read off the TPM, we can only extract the public part. 801 | 802 | While we refer to these keys as being special in some way, they are in fact the primary key for the endorsement hierarchy (EK) with a specific key generation template and a signing key derived from that (AK). The tpm2tools library provides convenience functions to generate these, hence their special nature. 803 | 804 | NOTE: this section contains an error - the diagrams in the EK section should show the Endorsement Hierarhcy. Issue raised (Ian) 805 | 806 | ### Endorsement key 807 | We can ask the TPM to generate the endorsement key with the following commnand: 808 | 809 | ```bash 810 | $ tpm2_createek -c 0x81010002 -G rsa -u ek.pub 811 | $ tpm2_getcap handles-persistent 812 | - 0x81010002 813 | - 0x81010020 814 | - 0x81010021 815 | ``` 816 | 817 | This will use a key derivation function (KDF) to generate a keypair from the TPM seed. 818 | The public part of this keypair will be written to the file `ek.pub` (in a TPM specific format) and it will store the key in persistent storage inside the TPM using handle `0x81010002`. 819 | We can use this handle on other commands to instruct the TPM to use the EK for some operations (more on this later). 820 | This allows us to use the EK in subsequent commands without having to generate it again each time. 821 | 822 | ![EK](./assets/ek.png "EK") 823 | 824 | 825 | We can read the public key from the handle using the following command: 826 | ```bash 827 | $ tpm2_readpublic -c 0x81010002 -o ek.pem -f pem 828 | name: 000b633b69cea48e41df39359bf8973058aab99d79d1e5ef966a505d4009b766e7e8 829 | qualified name: 000ba671796c9b4f647e033db4ebdf182a91495cd8889e15e30203126424944c8e7b 830 | name-alg: 831 | value: sha256 832 | raw: 0xb 833 | attributes: 834 | value: fixedtpm|fixedparent|sensitivedataorigin|adminwithpolicy|restricted|decrypt 835 | raw: 0x300b2 836 | type: 837 | value: rsa 838 | raw: 0x1 839 | exponent: 0x0 840 | bits: 2048 841 | scheme: 842 | value: null 843 | raw: 0x10 844 | scheme-halg: 845 | value: (null) 846 | raw: 0x0 847 | sym-alg: 848 | value: aes 849 | raw: 0x6 850 | sym-mode: 851 | value: cfb 852 | raw: 0x43 853 | sym-keybits: 128 854 | rsa: bfe4fbd70000b3cfbfa792cfa21dd2cdb944cef6322af5b1dceb61d6cd78c34e44f2494611779bc0f659df0a6d0769d6b627b9fbe52510ac77a7fc038395458dfe6c510bd50df1157083581c3c9af15547c80067f5894ebe586f0eac70f85b64bd9343050c63652ecfed7dbb6681fa38d7463ad3e8187c3156ccc18f3321b10fdd92b9d9cc1a8a68629ff837e296e92e66a78deeaaa3943a5fcc1b8dd6adc7927065109de0b7c55c866de4c1620d33cc2d803980e518a7e6fbd984fa2898f577033ccfc5a01612d29ecb44a08444f99ba0fc70fdc965e7544f32c0b7e9905000a59677ec66a3dd463341d102b94ae4ceb893104b06daf305315e32c7d77cb005 855 | authorization policy: 837197674484b3f81a90cc8d46a5d724fd52d76e06520b64f2a1da1b331469aa 856 | ``` 857 | 858 | Optionally, this command can save the EK into a file in a different format, e.g. PEM. 859 | 860 | ```bash 861 | $ cat ek.pem 862 | -----BEGIN PUBLIC KEY----- 863 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+T71wAAs8+/p5LPoh3S 864 | zblEzvYyKvWx3Oth1s14w05E8klGEXebwPZZ3wptB2nWtie5++UlEKx3p/wDg5VF 865 | jf5sUQvVDfEVcINYHDya8VVHyABn9YlOvlhvDqxw+FtkvZNDBQxjZS7P7X27ZoH6 866 | ONdGOtPoGHwxVszBjzMhsQ/dkrnZzBqKaGKf+DfilukuZqeN7qqjlDpfzBuN1q3H 867 | knBlEJ3gt8Vchm3kwWINM8wtgDmA5Rin5vvZhPoomPV3AzzPxaAWEtKey0SghET5 868 | m6D8cP3JZedUTzLAt+mQUACllnfsZqPdRjNB0QK5SuTOuJMQSwba8wUxXjLH13yw 869 | BQIDAQAB 870 | -----END PUBLIC KEY----- 871 | ``` 872 | 873 | ### Attestation key 874 | We can ask the TPM to generate the attestation key from the endorsement key and store it in a suitable handle in the TPM with the following commands: 875 | 876 | 877 | * `-C` tells us where the EK is, it could be a handle or context object 878 | * `-c` the output context object for the AK 879 | * `-G` the encryption algorithm to use 880 | * `-g` the hash algorithm 881 | * `-s` the signing algorithm 882 | * `-u` the public portion 883 | * `-f` the output type for the public portion 884 | * `-n` the name of the key (optional) 885 | 886 | 887 | ```bash 888 | $ tpm2_createak -C 0x81010002 -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub -f pem -n ak.name 889 | loaded-key: 890 | name: 000b580a1671f0b85748a42bcdd216162bd82aee1bf331815e43bbbc582d5d872751 891 | $ tpm2_evictcontrol -c ak.ctx 0x81010003 892 | persistent-handle: 0x81010003 893 | action: persisted 894 | ``` 895 | 896 | ![AK](./assets/ak.png "AK") 897 | 898 | 899 | 900 | The `tpm2_evictcontrol' is similar to earlier examples. 901 | 902 | This will use a KDF to create the attestation keypair. 903 | This KDF uses the EK as an input as well, because the AK is in the same key hierarchy as the EK. 904 | This command will also store the public part of the AK into `ak.pub` (in TPM specific format) and will make the AK persistent in handle `0x81010003` for later use. 905 | 906 | One thing to take note is that the AK is used for signing only and not for encryption/decryption, hence the use of the `-s rsassa` parameter. 907 | 908 | The AK's primary use is when signing quotes generated by the TPM. 909 | 910 | Technically any key that is able to sign structures can be utilised as 'an attestation key', however deriving an attestation key explicitly from the EK provides us with certain certificate chain and identification properties which may (or are) useful during the attestation and quoting process. 911 | -------------------------------------------------------------------------------- /docs/nvram.md: -------------------------------------------------------------------------------- 1 | # Using NVRAM 2 | The TPM contains some general purpose memory which can be used to store whatever you wish. 3 | Each defined area can also be protected - there are a number of mechanisms for this, and the process is called *sealing*. 4 | The most common way to seal NVRAM is to seal it against a particular combination of PCRs. 5 | 6 | - [Using NVRAM](#using-nvram) 7 | - [Handles](#handles) 8 | - [Listing NVRAM Areas](#listing-nvram-areas) 9 | - [Basics: Defining, Reading and Writing](#basics-defining-reading-and-writing) 10 | - [Defintion](#defintion) 11 | - [Writing](#writing) 12 | - [Reading](#reading) 13 | - [Writing and Reading Again](#writing-and-reading-again) 14 | - [Removing an NVRAM area](#removing-an-nvram-area) 15 | - [Counters](#counters) 16 | - [Defintion](#defintion-1) 17 | - [Read and Write Locking](#read-and-write-locking) 18 | - [Write locking](#write-locking) 19 | - [Read locking](#read-locking) 20 | - [Sealing](#sealing) 21 | - [Policy Creation](#policy-creation) 22 | - [Defining an NVRAM area with Policies](#defining-an-nvram-area-with-policies) 23 | - [Writing and Reading](#writing-and-reading) 24 | - [Changes to the PCRs](#changes-to-the-pcrs) 25 | - [Removal of the Policy Protected Area](#removal-of-the-policy-protected-area) 26 | 27 | 28 | ## Handles 29 | Each area of NVRAM is addressed by a handle. Typically NVRAM area handles are in the `0x1xxxxxxx` range. 30 | Other values may occur for specific reasons, but to remain true to the standard for TPMs, use this range. 31 | 32 | ## Listing NVRAM Areas 33 | The first command lists all the defined NVRAM areas and the properties of those areas: 34 | 35 | ```bash 36 | tpm2_nvreadpublic 37 | ``` 38 | 39 | This will print out a list, which even on a brand new TPM will probably contain items, for example, an entry looks like this. 40 | 41 | ```bash 42 | 0x1c0000a: 43 | hash algorithm: 44 | friendly: sha256 45 | value: 0xB 46 | attributes: 47 | friendly: ppwrite|writedefine|ppread|ownerread|authread|no_da|written|platformcreate 48 | value: 0x1200762 49 | size: 775 50 | ``` 51 | 52 | The first item `0x1c0000a` is the handle to the NVRAM area. 53 | The next two attributes `friendly` and `value` tell us which hash algorithm is being used and which attributes are set on the area. 54 | In both cases a raw value and the friendly, human readable form is presented. 55 | Finally the size of the area is provided - in this case 775 bytes. 56 | 57 | 58 | Note: TPMs typically come with a number of areas already defined and populated with data. The simualator however might be completely blank. So if you see or don't see anything don't be surprised. 59 | 60 | 61 | ## Basics: Defining, Reading and Writing 62 | In this section, we'll introduce the basic commands for handling NVRAM 63 | We will define, read, write and eventually remove NVRAM areas. 64 | 65 | ### Defintion 66 | To define an area we need to supply the following 67 | 68 | 1. handle - which should be not currently in use 69 | 2. hierarchy under which the handle will be defined, usually platform or owner 70 | 3. the size of the area in bytes 71 | 4. the attributes 72 | 73 | We define an area of 32 bytes, under the owner hierarchy at handle `0x1500016`. 74 | We also need to list the attributes of the NVRAM area. In this case we set this so anyone within the owner hierarchy can read and write if authorisation is given. 75 | Then we'll list the NVRAM areas. 76 | 77 | ```bash 78 | $ tpm2_nvdefine 0x1500016 -C o -s 32 79 | nv-index: 0x1500016 80 | $ tpm2_nvreadpublic 81 | 0x1500016: 82 | hash algorithm: 83 | friendly: sha256 84 | value: 0xB 85 | attributes: 86 | friendly: ownerwrite|authwrite|ownerread|authread 87 | value: 0x6000600 88 | size: 32 89 | ``` 90 | 91 | ![NVDefine](./assets/nvdefine.png "NVDefine") 92 | 93 | So, now we have an area that can be written to and read from by anyone under the owner hierarchy that gives the appropriate authorisations. 94 | 95 | ### Writing 96 | First, we define a file that contains some interesting information and then write it to the area: 97 | 98 | ```bash 99 | $ echo "Hello" > testfile 100 | $ cat testfile 101 | Hello 102 | $ tpm2_nvwrite 0x1500016 -C o -i testfile 103 | ``` 104 | 105 | ![NVWrite](./assets/nvwrite.png "NVWrite") 106 | 107 | 108 | The write command tells to write the contents of `./testfile/` into handle `0x1500016` and provide authorisation using the owner hierarchy. 109 | 110 | If we try to use the platform hierarchy here, we'll get an error: 111 | 112 | ```bash 113 | $ tpm2_nvwrite 0x1500016 -C p -i testfile 114 | WARNING:esys:src/tss2-esys/api/Esys_NV_Write.c:306:Esys_NV_Write_Finish() Received TPM Error 115 | ERROR:esys:src/tss2-esys/api/Esys_NV_Write.c:110:Esys_NV_Write() Esys Finish ErrorCode (0x00000149) 116 | ERROR: Failed to write NV area at index 0x1500016 117 | ERROR: Tss2_Sys_NV_Write(0x149) - tpm:error(2.0): NV access authorization fails in command actions 118 | ERROR: Unable to run tpm2_nvwrite 119 | ``` 120 | 121 | What happens if we try to write something larger than the defined area? 122 | ```bash 123 | $ cat testfile2 124 | This is certainly more than 32 bytes long 125 | $ wc testfile2 126 | 1 8 42 testfile2 127 | $ tpm2_nvwrite 0x1500016 -C o -i testfile2 128 | ERROR: The starting offset (0) and the size (42) are larger than the defined space: 32. 129 | ERROR: Unable to run tpm2_nvwrite 130 | ``` 131 | 132 | ### Reading 133 | Reading is made similarly by specifying the NVRAM handle and the authorisation hierarchy to use. 134 | 135 | ```bash 136 | $tpm2_nvread 0x1500016 -C o 137 | Hello 138 | �������������������������� 139 | ``` 140 | 141 | What's all the extra stuff? We can use hexdump to find out: 142 | 143 | ```bash 144 | $ tpm2_nvread 0x1500016 -C o | hexdump -c 145 | 0000000 H e l l o \n 377 377 377 377 377 377 377 377 377 377 146 | 0000010 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 147 | 0000020 148 | ``` 149 | 150 | So we have 32 bytes containing our text a newline (!!!) and the rest of the area is filled with octca 377, or decimal 255. 151 | This corresponds to an ASCII character which our terminal represents as a question mark glyph - it's a non-printing ASCII character. 152 | 153 | Note. even though we talk about ASCII characters, it really just is a set of bytes which our terminal renders as ASCII. 154 | 155 | 156 | You can even specify offsets, eg: start from the 3rd character and read 10 bytes: 157 | ```bash 158 | $ tpm2_nvread 0x1500016 -C o --offset 3 -s 10 159 | lo 160 | ������� 161 | ``` 162 | 163 | Again, run the above through hexdump to see what is precicely being returned. 164 | 165 | Note, the name of the offset parameter is `--offset`, because `-o` is used to write to a file instead of the console which can cause confusion: 166 | 167 | ```bash 168 | $tpm2_nvread 0x1500016 -o 3 169 | $ ls -l 3 170 | -rw-r--r-- 1 pi pi 32 Apr 6 17:00 3 171 | $ cat 3 172 | Hello 173 | ``` 174 | 175 | ### Writing and Reading Again 176 | You can write to an area as many time as you wish, but if you write something shorter, then the old contents will not be overwritten: 177 | 178 | ```bash 179 | $ echo "Hello Fred!" > testfile4 180 | $ tpm2_nvwrite 0x1500016 -C o -i testfile4 181 | $ tpm2_nvread 0x1500016 -C o 182 | Hello Fred! 183 | ``` 184 | 185 | As expected, BUT...hexdump provided so you can figure this out! 186 | 187 | ```bash 188 | $ echo "Bueno!" > testfile5 189 | $ tpm2_nvwrite 0x1500016 -C o -i testfile5 190 | $ tpm2_nvread 0x1500016 -C o 191 | Bueno! 192 | red! 193 | ``` 194 | 195 | ### Removing an NVRAM area 196 | Finally, we can remove our NVRAM area and check that it has gone by using the `tpm2_nvreadpublic` command, which lists all the NVRAM areas but hopefully without the one we've just removed. 197 | If it is still there then you've got other problems... 198 | 199 | ```bash 200 | $ tpm2_nvundefine 0x1500016 -C o 201 | $ tpm2_nvreadpublic 202 | ``` 203 | 204 | ## Counters 205 | It can be useful to use counters at times and NVRAM has a mechanism for supporting this. 206 | 207 | ### Defintion 208 | As before, we need to define an NVRAM area, but this time we will supply an additional parameter `nt=1` which provides information about the type of the contents, in this case it defines a counter. It is sometimes mistaken as the initial value of the counter. Counters always start at 0 when they are first written to by the `nv_increment` command. 209 | 210 | NOTE: Not all TPMs are mandated to support counters or the `nt` attribute. 211 | 212 | Counters probably don't need to be big, so a small size, eg: 8 bytes will do. 213 | 214 | ```bash 215 | $ tpm2_nvdefine 0x1500017 -C o -s 8 -a "ownerread|ownerwrite|policywrite|nt=1" 216 | ``` 217 | 218 | And if we try to read immediately after creation: 219 | 220 | ```bash 221 | $ tpm2_nvread 0x1500017 -C o 222 | WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:311:Esys_NV_Read_Finish() Received TPM Error 223 | ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x0000014a) 224 | ERROR: Esys_NV_Read(0x14A) - tpm:error(2.0): an NV Index is used before being initialized or the state saved by TPM2_ShutdownSTATE could not be restored 225 | ERROR: Failed to read NVRAM area at index 0x1500017 226 | ERROR: Unable to run tpm2_nvread 227 | ``` 228 | 229 | Surprising?! Well, this just means we've set up a counter but actually not written the counter, which we'll do like this: 230 | 231 | ```bash 232 | $ tpm2_nvincrement 0x1500017 -C o 233 | $ tpm2_nvread 0x1500017 -C o 234 | $ tpm2_nvread 0x1500017 -C o | hexdump -c 235 | 0000000 \0 \0 \0 \0 \0 \0 \0 001 236 | 0000008 237 | ``` 238 | 239 | Now it might be surprising that the first ``tpm2_nvread`` didn't print anything out, OR, it actually might have but it would have been incomprehensible, in other words your terminal might be trying to render whatever is returned as a non-printing ASCII character. 240 | But, as we can see in the hexdump, `001` is there and is the least significant byte. 241 | 242 | We can continue: 243 | 244 | ```bash 245 | $ tpm2_nvincrement 0x1500017 -C o 246 | $ tpm2_nvread 0x1500017 -C o | hexdump -c 247 | 0000000 \0 \0 \0 \0 \0 \0 \0 002 248 | 0000008 249 | $ tpm2_nvincrement 0x1500017 -C o 250 | $ tpm2_nvread 0x1500017 -C o | hexdump -c 251 | 0000000 \0 \0 \0 \0 \0 \0 \0 003 252 | 0000008 253 | ``` 254 | 255 | Now as an exercise take a look at what `tpm2_nvreadpublic` says and then remove the NVRAM area using the `tpm2_nvundefine` command. 256 | ## Read and Write Locking 257 | There exist two commands for preventing modification of an NVRAM area. 258 | 259 | CAUTION: If you lock an area it is not guaranteed, even after a powercycle that you'll get your data back or be able to write to that area again. 260 | You can always remove the area however. 261 | 262 | In order to allow this, we must tell the TPM to apply an additional attribute when creating the NVRAM areas. 263 | Take note of the `tpm2_nvdefine`. 264 | 265 | ### Write locking 266 | `tpm2_writelock` is NOT installed in the Fedora version of the course 267 | 268 | To enable write locking we need to apply the `write_stclear` attribute to the NVRAM area. 269 | 270 | Note: in some of the examples below we have removed the non-printing ASCII characters when reading from nvram just for presentation purposes. 271 | 272 | ```bash 273 | $ cat testfile 274 | Hello Fred! 275 | $ tpm2_nvdefine 0x1500018 -C o -s 32 -a "ownerread|policywrite|ownerwrite|write_stclear" 276 | nv-index: 0x1500018 277 | $ tpm2_nvwrite 0x1500018 -C o -i testfile 278 | $ tpm2_nvread 0x1500018 -C o 279 | Hello 280 | $ tpm2_nvwritelock 0x1500018 -C o 281 | $ tpm2_nvwrite 0x1500018 -C o -i testfile 282 | VAST AMOUNT OF TPM ERRORS!!! 283 | ``` 284 | 285 | ### Read locking 286 | To enable read locking we need to apply the `read_stclear` attribute to the NVRAM area 287 | ```bash 288 | $ tpm2_nvdefine 0x1500018 -C o -s 32 -a "ownerread|policywrite|ownerwrite|read_stclear" 289 | nv-index: 0x1500018 290 | $ tpm2_nvwrite 0x1500018 -C o -i testfile 291 | $ tpm2_nvread 0x1500018 -C o 292 | Hello 293 | $ tpm2_nvreadlock 0x1500018 -C o 294 | $ tpm2_nvread 0x1500018 -C o 295 | WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:311:Esys_NV_Read_Finish() Received TPM Error 296 | ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x00000148) 297 | ERROR: Esys_NV_Read(0x148) - tpm:error(2.0): NV access locked 298 | ERROR: Failed to read NVRAM area at index 0x1500018 299 | ERROR: Unable to run tpm2_nvread 300 | ``` 301 | 302 | There is one solution... 303 | 304 | ```bash 305 | $ tpm2_nvundefine 0x1500018 -C o 306 | ``` 307 | 308 | ## Sealing 309 | 310 | One attribute that we can apply to an NVRAM area is that of a policy which locks that area to a particular set of values of the PCRs. This is known as sealing. 311 | 312 | This allows us to lock areas if the system configuration has changed. For example, the disk encryption key might be sealed againt BIOS updates. 313 | 314 | The process for doing this will be to 315 | 316 | - create a policy 317 | - define an NVRAM area 318 | - read/write as necessary 319 | 320 | We will then show a change in PCR values and how this affects the reading of that NVRAM area. 321 | 322 | ### Policy Creation 323 | We create policies from PCRs, for example: 324 | 325 | ```bash 326 | $ tpm2_pcrread sha256:0,1,2,3 327 | sha256: 328 | 0 : 0xF8F136C6AE76DA085F72955532FE500F1B00C9AFFC039CEF68F2C696525F9A97 329 | 1 : 0x4C76D8244FD0502508748526C8762917347D1BC99AD96B93FAD7BEF3B92F2E07 330 | 2 : 0x23FC7055C7C4210F0642246EC2A0DC6C7E4F8481D8D816A9A35E4845ECE03629 331 | 3 : 0x3F05A50B6DACAD2EB5318DFC0F1BB1DFCFBC06D13A8B420BF41D3DC0731DDD15 332 | ``` 333 | 334 | Now we create a policy. 335 | Firstly, we select the PCRs and save these in a file. 336 | 337 | ![nvpcrpolicy](./assets/nvpcrpolicy.png "nvpcrpolicy.png") 338 | 339 | 340 | ```bash 341 | $ tpm2_pcrread -o srtm.pcrvalues sha256:0,1,2,3 342 | sha256: 343 | 0 : 0xF8F136C6AE76DA085F72955532FE500F1B00C9AFFC039CEF68F2C696525F9A97 344 | 1 : 0x4C76D8244FD0502508748526C8762917347D1BC99AD96B93FAD7BEF3B92F2E07 345 | 2 : 0x23FC7055C7C4210F0642246EC2A0DC6C7E4F8481D8D816A9A35E4845ECE03629 346 | 3 : 0x3F05A50B6DACAD2EB5318DFC0F1BB1DFCFBC06D13A8B420BF41D3DC0731DDD15 347 | $ ls -l srtm.pcrvalues 348 | -rw-r--r-- 1 pi pi 128 Apr 7 21:19 srtm.pcrvalues 349 | ``` 350 | 351 | Now we create a policy, 352 | 353 | - `--policy-pcr` specifies that we are creating a policy from PCRs 354 | - `-l sha256:0,1,2,3` specifies which PCRs 355 | - `-f srtm.pcrvalues` spcified the file in which we stored the PCR values from earlier 356 | - `-L strm.policy` specifies the output file for the policy 357 | 358 | ```bash 359 | $ tpm2_createpolicy --policy-pcr -l sha256:0,1,2,3 -f srtm.pcrvalues -L srtm.policy 360 | 24b2257d66895473211bf35834d0be287cb2daf190bedeae0838909eb58551fb 361 | ``` 362 | 363 | 364 | ### Defining an NVRAM area with Policies 365 | We create an area as before, except this time we specify the policy file and attributes that state that reading and writing can only be made according to a given policy. 366 | 367 | ```bash 368 | $ tpm2_nvdefine 0x1500019 -C o -s 32 -L srtm.policy -a "policyread|policywrite" 369 | nv-index: 0x1500019 370 | ``` 371 | 372 | Note that the area is created under the owner hierarchy - take note! 373 | 374 | ![nvdefinepcrpolicy](./assets/nvdefinepcrpolicy.png "nvdefinepcrpolicy.png") 375 | 376 | 377 | ### Writing and Reading 378 | So, as before we must write to the NVRAM area. 379 | 380 | ```bash 381 | $ tpm2_nvwrite 0x1500019 -C o -i testfile 382 | WARNING:esys:src/tss2-esys/api/Esys_NV_Write.c:306:Esys_NV_Write_Finish() Received TPM Error 383 | ERROR:esys:src/tss2-esys/api/Esys_NV_Write.c:110:Esys_NV_Write() Esys Finish ErrorCode (0x00000149) 384 | ERROR: Failed to write NV area at index 0x1500019 385 | ERROR: Tss2_Sys_NV_Write(0x149) - tpm:error(2.0): NV access authorization fails in command actions 386 | ERROR: Unable to run tpm2_nvwrite 387 | ``` 388 | 389 | This time we get an access authorisation failure. 390 | What we have done is change where the TPM looks for authorisation - so it is no longer the owner hierarchy as we have previously defined but the authorisation policy we have bound to the NVRAM area. 391 | In this case we have *sealed* the TPM to the policy. 392 | To write we must provide the authorisation. 393 | 394 | ```bash 395 | $ tpm2_nvwrite 0x1500019 -C 0x1500019 -P pcr:sha256:0,1,2,3=srtm.pcrvalues -i testfile 396 | ``` 397 | 398 | This time we specify the following 399 | 400 | * `0x1500019` is the nvram handle 401 | * `0x1500019` is the location of the authorisation policy, which is stored within NVRAM areas 402 | * `-i testfile` is the input file 403 | * `-P pcr:sha256:0,1,2,3=srtm.pcrvalues` is the authorisation policy, which states that we collect the values of PCRs `sha256:0,1,2,3` and match them against the values generated earlier. 404 | 405 | As you can guess reading is similar where we need to specify the location of the authorisation handle and authorisation policy as before: 406 | 407 | ```bash 408 | $ tpm2_nvread 0x1500019 -C 0x1500019 -P pcr:sha256:0,1,2,3=srtm.pcrvalues 409 | Hello 410 | �������������������������� 411 | ``` 412 | 413 | ### Changes to the PCRs 414 | We will now work through an example. 415 | 416 | Firstly we take the hashes of two important files and load these into some PCRs. 417 | 418 | We then create a policy based on these and create an NVRAM area in which we will store a secret (or some configuration data, or whatever) that can only be accessed if those files remain unchanged. 419 | 420 | We will then change the files and reload the PCRs as if the machine was being rebooted. 421 | 422 | Firsly let's set up the PCRs. Because we're working on the simulator we'll reset the PCR because to its initial power on value so things remain sane here. 423 | 424 | We use PCR 23 because it is always accessible to user applications under the locality restrictions. 425 | 426 | We can use `tpm2_pcrevent` to combine the hashing and extention into one command. Here we've just made the whole process explicit. 427 | 428 | ```bash 429 | $ echo "Important File" > importantfile 430 | $ sha256sum importantfile 431 | 9accd0e5d4870154a11283b7c7d03ee0a2bb23fdc8a74ec3da9bb47735ffa286 importantfile 432 | $ tpm2_pcrreset 23 433 | $ tpm2_pcrread sha256:23 434 | $ tpm2_pcrextend 23:sha256= 435 | $ tpm2_pcrread sha256:23 436 | sha256: 437 | 23: 0xA627D2393558018DAB64CEC80E65AAD3EFDBD4D7F5237E8DA41E70E9F02DBDD3 438 | ``` 439 | 440 | Note that the value in the PCR is the *extension* of the previous value with the new value! 441 | 442 | Secondly, generate the policy and NVRAM area and write some data into that - and check it with a read. 443 | We'll ignore the output until the very last command in the example below for convenience. 444 | 445 | ```bash 446 | $tpm2_pcrread -o important.pcrvalues sha256:23 447 | $tpm2_createpolicy --policy-pcr -l sha256:23 -f important.pcrvalues -L important.policy 448 | $tpm2_nvdefine 0x1500020 -C o -s 32 -L important.policy -a "policyread|policywrite" 449 | $echo -n "A_big_secret" | tpm2_nvwrite 0x1500020 -C 0x1500020 -P pcr:sha256:23=important.pcrvalues -i - 450 | $tpm2_nvread 0x1500020 -C 0x1500020 -P pcr:sha256:23=important.pcrvalues 451 | A_big_secret�������������������� 452 | ``` 453 | 454 | and of course if we get things wrong, for example, specifying the wrong PCRs to generate the current values to check against the policy: 455 | 456 | ```bash 457 | $ tpm2_nvread 0x1500020 -C 0x1500020 -P pcr:sha256:22=important.pcrvalues 458 | WARNING:esys:src/tss2-esys/api/Esys_PolicyPCR.c:288:Esys_PolicyPCR_Finish() Received TPM Error 459 | ERROR:esys:src/tss2-esys/api/Esys_PolicyPCR.c:100:Esys_PolicyPCR() Esys Finish ErrorCode (0x000001c4) 460 | ERROR: Esys_PolicyPCR(0x1C4) - tpm:parameter(1):value is out of range or is not correct for the context 461 | ERROR: Invalid handle authorization 462 | ERROR: Unable to run tpm2_nvread 463 | ``` 464 | 465 | Now, we assume our system gets rebooted and someone has tampered with our important file. During boot it is remeasured: 466 | 467 | ```bash 468 | $ rm important.pcrvalues 469 | $ rm important.policy 470 | $ echo "Really Important File" > importantfile 471 | $ sha256sum importantfile 472 | 06ffaf725651f7fcda018202f6e2661350e51efaff3d02c3b5720668b954d72f importantfile 473 | $ tpm2_pcrreset 23 474 | $ tpm2_pcrread sha256:23 475 | $ tpm2_pcrextend 23:sha256= 476 | $ tpm2_pcrread sha256:23 477 | sha256: 478 | 23: 0x36348FD1CAB7772FB2421C94BB75F727ED7ADD83A3972045FB2A84337721E4ED 479 | ``` 480 | 481 | Now, to read the data we must recreate the PCR values 482 | 483 | ```bash 484 | $ tpm2_pcrread -o hackingattempt.pcrvalues sha256:23 485 | sha256: 486 | 23: 0x36348FD1CAB7772FB2421C94BB75F727ED7ADD83A3972045FB2A84337721E4ED 487 | $ tpm2_nvread 0x1500020 -C 0x1500020 -P pcr:sha256:23=hackingattempt.pcrvalues 488 | WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:311:Esys_NV_Read_Finish() Received TPM Error 489 | ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x0000099d) 490 | ERROR: Esys_NV_Read(0x99D) - tpm:session(1):a policy check failed 491 | ERROR: Failed to read NVRAM area at index 0x1500020 492 | ERROR: Unable to run tpm2_nvread 493 | ``` 494 | 495 | And if we try to write, we get a similar answer: 496 | 497 | ```bash 498 | $ echo -n "New data" | tpm2_nvwrite 0x1500020 -C 0x1500020 -P pcr:sha256:23=hackingattempt.pcrvalues -i - 499 | WARNING:esys:src/tss2-esys/api/Esys_NV_Write.c:306:Esys_NV_Write_Finish() Received TPM Error 500 | ERROR:esys:src/tss2-esys/api/Esys_NV_Write.c:110:Esys_NV_Write() Esys Finish ErrorCode (0x0000099d) 501 | ERROR: Failed to write NV area at index 0x1500020 502 | ERROR: Tss2_Sys_NV_Write(0x99D) - tpm:session(1):a policy check failed 503 | ERROR: Unable to run tpm2_nvwrite 504 | ``` 505 | 506 | In order to gain access to that data we need: 507 | 508 | * To know the PCRs used to create the policy 509 | * To have the correct values in the PCRs 510 | 511 | Without both of these we can not extract the data from that NVRAM area. The only thing to do is to delete area. 512 | 513 | 514 | ### Removal of the Policy Protected Area 515 | As always you can remove NVRAM areas as this always results in the data being lost forever - a good option from a hard security perspective. 516 | In order to do this we must provide authorisation from one of the hierarchies...any hierarchy can be used. 517 | 518 | ```bash 519 | $ tpm2_nvundefine -C o 0x1500020 520 | ``` 521 | 522 | 523 | 524 | -------------------------------------------------------------------------------- /docs/objects.md: -------------------------------------------------------------------------------- 1 | # TPM Objects 2 | - [TPM Objects](#tpm-objects) 3 | - [Handles](#handles) 4 | - [Hierarchies](#hierarchies) 5 | - [Taking Ownership](#taking-ownership) 6 | - [Dictionary Lockout](#dictionary-lockout) 7 | - [Clearing the TPM](#clearing-the-tpm) 8 | - [Resetting Seeds](#resetting-seeds) 9 | - [Attributes](#attributes) 10 | - [Locality](#locality) 11 | 12 | The TPM contains a number of objects such as keys, NVRAM areas, PCRs etc. These are addressed using handles - basically a pointer to the object. 13 | 14 | Each object exists in one of the four authorisation hierarchies in the TPM: platform, owner, endorsement and null - these will be explained later. 15 | 16 | Each object has a set of attributes associated with it that provides information about what kinds of authorisation are required, information about the object itself and so on. 17 | 18 | Finally, there is a notion called locality which further controls who can access and modify objects. 19 | 20 | ## Handles 21 | A handle is a 32 bit number that is used to refer to an object stored in the TPM. Typically we write these in hexadecimal notation. 22 | 23 | The upper byte(s) tells us what kind of object the handle points to. 24 | 25 | * `0x80......` - transient objects 26 | * `0x8100....` - owner hierarchy keys 27 | * `0x8101....` - endorsement hierarchy keys 28 | * `0x8180....` - platofrm hierachy keys 29 | * `0x01......` - NVRAM 30 | * `0x01c1....` - NVRAM areas that the TCG has reserved for particular organisations/uses 31 | * `0x01c2....` - NVRAM areas that the TCG has reserved for OEMs, eg: Infineon 32 | * `0x01c2....` - NVRAM areas that the TCG has reserved for platform OEMs 33 | * `0x40......` - Permanent objects (eg: references to hierarchies) 34 | 35 | The handles can be listed using the `tpm2_getcap` command. 36 | 37 | * `-l` lists the capability categories of the TPM, for example: 38 | 39 | ```bash 40 | $ tpm2_getcap -l 41 | - algorithms 42 | - commands 43 | - pcrs 44 | - properties-fixed 45 | - properties-variable 46 | - ecc-curves 47 | - handles-transient 48 | - handles-persistent 49 | - handles-permanent 50 | - handles-pcr 51 | - handles-nv-index 52 | - handles-loaded-session 53 | - handles-saved-session 54 | $ tpm2_getcap handles-permanent 55 | - 0x40000001 56 | - 0x40000007 57 | - 0x40000009 58 | - 0x4000000A 59 | - 0x4000000B 60 | - 0x4000000C 61 | - 0x4000000D 62 | ``` 63 | 64 | These handles refer to the various authorisation hierarchies: platform, owner, endorsement and null; the lockout password and other structures inside the TPM. 65 | 66 | 67 | ## Hierarchies 68 | The TPM has four hierachies that are used to group objects together for specific use cases. The hierarchies are: 69 | 70 | * Platform 71 | * Owner (sometimes called Storage) 72 | * Endorsement 73 | * Null 74 | 75 | Each hierarchy is used to define an authorisation to access and use the objects it contains. Typically this is done using a password. 76 | 77 | One use of the hierarchies is during the manufacturing and provisioning of a TPM: 78 | 79 | * The manufacturer may place keys or NVRAM areas under the Endorsement hierarchy and then lock it 80 | * The OEM may place keys or NVRAM areas under the Platform hierarchy and then lock it (see note below) 81 | * The Owner hierarchy is open to the end-user 82 | * The null hierarchy is used internally by the TPM for anything temporary, eg: session information etc. 83 | 84 | The reason for locking these areas is to facilitate revocation of keys and other data, as well as keeping manufacturer or OEM specific data safe. 85 | 86 | Each hierarchy has a seed from which keys are derived. It is possible - on some TPMs - to reset these seeds rendering any keys, policies and NVRAM areas under that hierarhy no longer accessible or usable. 87 | 88 | The platform hierarchy is interesting as its password is always reset when a power cycle happens. This is because this hierarchy was aimed at platform manufacturers and OEMs who want control over their parts of the system, eg: firmware signatures etc. But, if something needed changing, eg: a firmware update, then it would be necessary to unlock this hierarchy. The solution is that the platform hierarchy is open until device start and then a random password written there to lock it for the duration of usage. Unlocking this hierarchy would be part of a hardware update process. 89 | 90 | In these exercises use the owner hierarchy - it is what it was designed for. 91 | 92 | ### Taking Ownership 93 | Note, there used to be a command called `takeownership` which is kind of a hangover from the TPM 1.2 days when such a concept existed. It was modified to call the TPM 2.0 equivalents and has over the years caused some confusion about what taking ownership actually meant. TPM 2.0 has hierarchies, while TPM 1.2 didn't ... if someone is talking about taking ownership then it is time for a longer conversation on exactly what they want. This is not a discussion we will have here but it is good to be aware. 94 | 95 | To set the passwords on the hierarchies, typically when a TPM is first used, we set three passwords using `tpm2_changeauth`. 96 | 97 | * `owner` or `o` sets the owner hierarchy password 98 | * `endorsement` or `e` sets the endorsement hierarchy password 99 | * `lockout` or `l` sets the lockout password 100 | 101 | WARNING #1: This is a potentially dangerous command. Practice with the simulator and not on a real TPM. There will be more warnings later. 102 | 103 | ```bash 104 | $ tpm2_changeauth -c owner password1 105 | $ tpm2_changeauth -c endorsement password2 106 | $ tpm2_changeauth -c lockout password3 107 | ``` 108 | 109 | The lockout password is used the unlock the password from the dictionary attack state. If someone enters a password incorrectly mulitple times the TPM will lock. In some cases this lockout period might be over 24 hours! 110 | 111 | WARNING #2: We recommend when testing and practicing the commands here that you DO NOT SET ANY PASSWORDS. 112 | 113 | WARNING #3: If you forget or incorrectly set the passwords then you will lose access to the TPM....forever! 114 | 115 | To change the password, supply the old password via `-p` and the new password. 116 | 117 | ```bash 118 | $ tpm2_changeauth -c o -p password1 passwordA 119 | $ tpm2_changeauth -c e -p password2 passwordB 120 | $ tpm2_changeauth -c l -p password3 passwordC 121 | ``` 122 | 123 | You can also clear all the passwords by supplying the lockout password like so 124 | 125 | 126 | 127 | 128 | ### Dictionary Lockout 129 | WARNING: THIS COULD RESULT IN YOU BEING LOCKED OUT OF YOUR TPM FOR EITHER A LONG TIME OR PERMANENTLY! 130 | 131 | To prevent continuous attempt to access objects on a TPM, the device employs a protection called dictionary lockout. 132 | 133 | When the TPM fails with a lockout error then it is necesary to supply the dictionary lockout password - stored one of the permanent handles and set with the `tpm2_changeauth` command. 134 | 135 | The command for setting the properites of the lockout is as follows: 136 | 137 | ```bash 138 | tpm2_dictionarylockout -s -n 5 -t 6 -l 7 -p passwordC 139 | ``` 140 | 141 | TODO: rewrite this so it isn't a copy of the man page. 142 | 143 | * `-s` Specifies the tool should operate to setup dictionary-attack-lockout parameters. 144 | * `-c` clear-lockout: Specifies the tool should operate to clear dictionary-attack-lockout state. 145 | * `-l` --lockout-recovery-time=NATURAL_NUMBER. Specifies the wait time in seconds before another TPM_RH_LOCKOUT authentication attempt can be made after a failed authentication. 146 | * `-t` --recovery-time=NATURAL_NUMBER: Specifies the wait time in seconds before another DA-protected-object authentication attempt can be made after max-tries number of failed authentications. 147 | * `-n` --max-tries=NATURAL_NUMBER: Specifies the maximum number of allowed authentication attempts on DA-protected-object; after which DA is activated. 148 | * `-p` --auth=AUTH: The authorization value for the lockout handle. 149 | 150 | 151 | 152 | 153 | ### Clearing the TPM 154 | WARNING: THIS IS A VERY DANGEROUS, NON-REVERSABLE OPERATION WHICH WILL RESET THE TPM AND REGENERATE THE SEEDS. 155 | 156 | To clear a hierarchy, we need to specify it with the `-c` option. 157 | We can use `p` for plaform, `e` for endorsement and `o` for owner. 158 | For example, to clear the platform hierarchy, we would use the following command: 159 | 160 | ```bash 161 | $ tpm2_clear -c p 162 | ``` 163 | 164 | We can also clear the lockout password mentioned in the previous section, by using `l` as an argument for the `-c` option: 165 | 166 | ```bash 167 | $ tpm2_clear -c l 168 | ``` 169 | 170 | 171 | 172 | 173 | ### Resetting Seeds 174 | WARNING: THIS IS A VERY DANGEROUS, NON-REVERSABLE OPERATION WHICH WILL RESET THE TPM AND REGENERATE THE SEEDS. 175 | 176 | To reset the seeds to generate the primary keys for the platform and endorsement hierarchies: 177 | 178 | ```bash 179 | $ tpm2_changepps 180 | ``` 181 | 182 | If a password has been set with `tpm2_changeauth` then the above commands take the option `-p` followed by the password for that hierarchy. 183 | 184 | ```bash 185 | $ tpm2_changepps -p 186 | ``` 187 | 188 | 189 | ## Locality 190 | Locality is a mechanism that is used to tell the TPM what state the system is in. 191 | When locality is applied to PCR registers, it controls who can extend and reset those registers. 192 | 193 | The TCG defines a number of localities, of which 0 to 4 are typically in use. 194 | To use other localities one must refer to the TCG. 195 | Examples of usage are below: 196 | 197 | * Locality 0 is used to control access to PCRs that can be modified and reset by the CRTM 198 | * Locality 1 is used to control access to PCRs that can be modified and reset by the SRTM 199 | * Locality 2 is used to control access to PCRs that can be modified and reset by the Late launch 200 | * Locality 3 is used to control access to PCRs that can be modified and reset by the Kernel 201 | * Locality 4 is used to control access to PCRs that can be modified and reset by the User/Run-time environemnt 202 | 203 | For example, in normal operation PCRs 16 and 23 are defined under locality 4 which means the user can reset and extend these PCRs. 204 | PCR 0 is under locality 0, which means only the intial CRTM code can modify this PCR. 205 | 206 | Locality is a complex topic but knowing that the TPM might refuse certain operations on PCRs and this is the reason why will help in understanding some errors. Locality is described earlier in this tutorial and normally we don't worry about it. 207 | 208 | Locality is a complex topic but knowing that the TPM might refuse certain operations on PCRs and this is the reason why will help in understanding some errors. Locality is described earlier in this tutorial and normally we don't worry about it. 209 | 210 | -------------------------------------------------------------------------------- /docs/pcrs.md: -------------------------------------------------------------------------------- 1 | # Platform Configuration Registers 2 | - [Platform Configuration Registers](#platform-configuration-registers) 3 | - [Reading PCRs](#reading-pcrs) 4 | - [Reading all PCRs from all banks](#reading-all-pcrs-from-all-banks) 5 | - [Reading a set of PCRs](#reading-a-set-of-pcrs) 6 | - [Reading a single bank of PCRs](#reading-a-single-bank-of-pcrs) 7 | - [Extending PCRs](#extending-pcrs) 8 | - [Resetting a PCR](#resetting-a-pcr) 9 | - [Extending a PCR with the hash of file](#extending-a-pcr-with-the-hash-of-file) 10 | 11 | The TPM contains a number of banks of registers used for storing measurements - typically of boot time measurements - these are a fundamental part of the measured boot mechanism and form a core part of the policy, sealing, reporting and attestation mechanisms that much of the idea of trusted computing is based on. 12 | 13 | The TCG TPM 2.0 standard (as of writing) states that there must be at least two banks, one SHA1 and one SHA256, containing 24 registers. The TCG x86 Boot Standard states that some of these registers are to be populated during a measured boot and certain registers are used for specific purposes, eg: CRTM, BIOS measures. 14 | 15 | ## Reading PCRs 16 | 17 | ### Reading all PCRs from all banks 18 | ```bash 19 | [fedora@vm021273 ~]$ tpm2_pcrread 20 | sha1: 21 | 0 : 0x7EBA0CFB74F41FEBCCDD1251F02BC208052B6023 22 | 1 : 0xB8720B5234E2F08CFA87069F172CBB43F0F08225 23 | 2 : 0x86FA03B9C721AF57DE8FB1C43CC3FE7B0A42239A 24 | 3 : 0xB2A83B0EBF2F8374299A5B2BDFC31EA955AD7236 25 | 4 : 0xAB705AAE41789E02A1909B2CBB8BFC0806115004 26 | 5 : 0x7B25D2EABBA18DC910E724A0C75020F1FEC80BE2 27 | 6 : 0xB2A83B0EBF2F8374299A5B2BDFC31EA955AD7236 28 | 7 : 0x518BD167271FBB64589C61E43D8C0165861431D8 29 | 8 : 0xC3DF1A5D37AC51163C63320F28B9C1C1FD933BD2 30 | 9 : 0x944C3EFEB668CB217B260F7D4B594DA4341E6FF2 31 | 10: 0xA3500BFF7A194B447D7FE57A089DED8D29581DBE 32 | 11: 0x0000000000000000000000000000000000000000 33 | 12: 0x0000000000000000000000000000000000000000 34 | 13: 0x0000000000000000000000000000000000000000 35 | 14: 0x0000000000000000000000000000000000000000 36 | 15: 0x0000000000000000000000000000000000000000 37 | 16: 0x0000000000000000000000000000000000000000 38 | 17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 39 | 18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 40 | 19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 41 | 20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 42 | 21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 43 | 22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 44 | 23: 0x0000000000000000000000000000000000000000 45 | sha256: 46 | 0 : 0xDE7022997F99B5DB26C9D64FB4C7AB83A1B1FAAAC24FF3E3936F002F3A53BD9B 47 | 1 : 0x0E45F4E9217FF2305B599C74C005B5F20C40515E063A5077CAA0310D4209D527 48 | 2 : 0x28D1B29995FDB6288D86B5905E79002B35F24705437FE62AD57293CD04FDBAA6 49 | 3 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969 50 | 4 : 0xE7BD29E5572B42709E0F6EAB4423713D3424A5CD3221EBF49721DCC909FA9001 51 | 5 : 0xB6E968CD86966C6B3DEAC77B2E7613DC414CFA5B99598209B321D0DFD6CCB864 52 | 6 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969 53 | 7 : 0x65CAF8DD1E0EA7A6347B635D2B379C93B9A1351EDC2AFC3ECDA700E534EB3068 54 | 8 : 0x56ABAC0E1C907D7CBF58EE60AB68538F727F6AC116C8785B67C07E39A1AD3F27 55 | 9 : 0x5EAE243245C62F9AD0528CC7858C4366C7891AB4615132F206077C49A8838DA9 56 | 10: 0x8848D3C10FB47F4073A2F06C03300294412D07245BD06DCEDDECAC71C31B6F2C 57 | 11: 0x0000000000000000000000000000000000000000000000000000000000000000 58 | 12: 0x0000000000000000000000000000000000000000000000000000000000000000 59 | 13: 0x0000000000000000000000000000000000000000000000000000000000000000 60 | 14: 0x0000000000000000000000000000000000000000000000000000000000000000 61 | 15: 0x0000000000000000000000000000000000000000000000000000000000000000 62 | 16: 0x0000000000000000000000000000000000000000000000000000000000000000 63 | 17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 64 | 18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 65 | 19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 66 | 20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 67 | 21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 68 | 22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 69 | 23: 0x0000000000000000000000000000000000000000000000000000000000000000 70 | sha384: 71 | 0 : 0x3107B2455FCE38B2779296D0A8B951AA9DA268D36AF270B0E38E84D4FA8EBAE25E4191CB5490BF00A1C6E94BBE2BC03E 72 | 1 : 0x6594397CDB6033A406E349FEED7836BF02DD1D574C724660BE8BA0E82627768D1333F835B2FF8D006F0BEE6A6152223D 73 | 2 : 0xDCD2E666AC30040F3BFA1E7C8F546FEBC94DBFF78831D8A4DF310DE2105FE3F0E0088FDC668137A36831C4D64737A78D 74 | 3 : 0x518923B0F955D08DA077C96AABA522B9DECEDE61C599CEA6C41889CFBEA4AE4D50529D96FE4D1AFDAFB65E7F95BF23C4 75 | 4 : 0xEE0507B6B5A3DB4477DFE08CD16E6C616FAE7A76CBC074719B9410D435FFF2E539249E7A4AC50C1C27F780B046DE5698 76 | 5 : 0xA553D02AC8C368C6930A3DF65EF9E62A4E575270A9BDEB7968C0E2E1BF754A924E0EDFE932FFD4A00CE214B9C3A10A7E 77 | 6 : 0x518923B0F955D08DA077C96AABA522B9DECEDE61C599CEA6C41889CFBEA4AE4D50529D96FE4D1AFDAFB65E7F95BF23C4 78 | 7 : 0x98441C7F7625D10058C47683AEC486CE311C633235EB555593A7EE791121E3578AE72D04ECEF661F272D59058B77AF35 79 | 8 : 0xB8D008A7BF95B99ADD4764A35F17E5861E47D3FE408B419BC3F06E56D88B419F61E56F60AB16EECCE3BF39542E8E63BC 80 | 9 : 0x0D16C863CBFFAA0CD007FA978CB6D6730710FB68FA5670E18EE14A6C5DDA0DD60058125484E1153479A6B3AE84196DC2 81 | 10: 0x5C58E808B7B40D97A4A7EAD5E70A8E4CB00A74A595B2F3EC7D021110C30A09B7A5823503EB5A217193DED5D9ED905B32 82 | 11: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 83 | 12: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 84 | 13: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 85 | 14: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 86 | 15: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 87 | 16: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 88 | 17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 89 | 18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 90 | 19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 91 | 20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 92 | 21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 93 | 22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 94 | 23: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 95 | sha512: 96 | 0 : 0x45826319AE145538E1F5313E5858D6575F527E0A9FF87B6979F896A7D3C4D596255C9CE6CDB822CD50716490340F2091E2021CF23445A00262EB21C7CB9A1E31 97 | 1 : 0x8B0A84F288E65721005ED74380FA6C0A9845736DFA555476B5CBE7610558C087DEF937F06F10CCFCC0DC405D2C4EBFCB8478EA1329589CC27DC38632A5F273B9 98 | 2 : 0xE4D3BD4A23871FEC350D4FCB362D90E3C3EE341D4AEB09B19AFF0E6CC82FC36F2CAD7DD8EF54A681D02F77F7EFDF68AF1274BBFD1C46A1DCF63691E9A6E09E22 99 | 3 : 0x27EC091533C4B9EEA38DD14C3A3ECDEF0A99C1E564CBE66DFE008250154E7839B0B75228FE8DEBCC4CA330E6AEBC1ABC74070BC9C9C1E26B939C9D916E45E13C 100 | 4 : 0x7E4EB1A1758187BB11162D04643C26C62FC7B2D743FDDD058021DA727DD0D61A6263A6FD8D10789566BB1F63EA9253E96AF5944E8F5B8DB17E04F2F4EA162672 101 | 5 : 0x0CF5C79591EB7218276AF2EC0C18C891568912D946AC9C8F2693E77CAA7B16368F7E5B2C117DF92E75286A4436575276C26032979BB097ED8AB5329C2C04A414 102 | 6 : 0x27EC091533C4B9EEA38DD14C3A3ECDEF0A99C1E564CBE66DFE008250154E7839B0B75228FE8DEBCC4CA330E6AEBC1ABC74070BC9C9C1E26B939C9D916E45E13C 103 | 7 : 0x7793D61D41CF40AE7CBF782DCAC336AB5D8546D8B6C369FBA740C784E16D4EC83247AF2043F6352790A9EB9AAB9C95EF318E5DD22C788E0848A10F8C87472A3E 104 | 8 : 0xA8A3D62463B3FF6C334B60A7CB3BA20D2FC1A1A70F6BA3AAFF473AD5654A3BCF9DA136DBC4328AAA5D1D229FB45CA8AE48804E9E76FA08469D3BCB54666590EE 105 | 9 : 0xC004F7B3BAC29026C84845599D78672FCCAFB22F9D99997F33E7AF78B5ACB86D520CA2D7C3C37CE88B4AB6F52607D40785AC9AF00C98F6B59216056BFECC52DB 106 | 10: 0x76153EAA35A8313E8CBE51CE540B5BEE5CC6FF1894D5EC0C2A0902FA7FF3ACBE573346C2695EA358B9006D10DDCACBB23A02604F423A160D8170640E61066A21 107 | 11: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 108 | 12: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 109 | 13: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 110 | 14: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 111 | 15: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 112 | 16: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 113 | 17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 114 | 18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 115 | 19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 116 | 20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 117 | 21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 118 | 22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 119 | 23: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 120 | ``` 121 | 122 | ### Reading a set of PCRs 123 | ```bash 124 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:0+sha256:0+sha384:0+sha512:0 125 | sha1: 126 | 0 : 0x7EBA0CFB74F41FEBCCDD1251F02BC208052B6023 127 | sha256: 128 | 0 : 0xDE7022997F99B5DB26C9D64FB4C7AB83A1B1FAAAC24FF3E3936F002F3A53BD9B 129 | sha384: 130 | 0 : 0x3107B2455FCE38B2779296D0A8B951AA9DA268D36AF270B0E38E84D4FA8EBAE25E4191CB5490BF00A1C6E94BBE2BC03E 131 | sha512: 132 | 0 : 0x45826319AE145538E1F5313E5858D6575F527E0A9FF87B6979F896A7D3C4D596255C9CE6CDB822CD50716490340F2091E2021CF23445A00262EB21C7CB9A1E31 133 | ``` 134 | 135 | ### Reading a single bank of PCRs 136 | ```bash 137 | [fedora@vm021273 ~]$ tpm2_pcrread sha1 138 | sha1: 139 | 0 : 0x7EBA0CFB74F41FEBCCDD1251F02BC208052B6023 140 | 1 : 0xB8720B5234E2F08CFA87069F172CBB43F0F08225 141 | 2 : 0x86FA03B9C721AF57DE8FB1C43CC3FE7B0A42239A 142 | 3 : 0xB2A83B0EBF2F8374299A5B2BDFC31EA955AD7236 143 | 4 : 0xAB705AAE41789E02A1909B2CBB8BFC0806115004 144 | 5 : 0x7B25D2EABBA18DC910E724A0C75020F1FEC80BE2 145 | 6 : 0xB2A83B0EBF2F8374299A5B2BDFC31EA955AD7236 146 | 7 : 0x518BD167271FBB64589C61E43D8C0165861431D8 147 | 8 : 0xC3DF1A5D37AC51163C63320F28B9C1C1FD933BD2 148 | 9 : 0x944C3EFEB668CB217B260F7D4B594DA4341E6FF2 149 | 10: 0xA3500BFF7A194B447D7FE57A089DED8D29581DBE 150 | 11: 0x0000000000000000000000000000000000000000 151 | 12: 0x0000000000000000000000000000000000000000 152 | 13: 0x0000000000000000000000000000000000000000 153 | 14: 0x0000000000000000000000000000000000000000 154 | 15: 0x0000000000000000000000000000000000000000 155 | 16: 0x0000000000000000000000000000000000000000 156 | 17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 157 | 18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 158 | 19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 159 | 20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 160 | 21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 161 | 22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 162 | 23: 0x0000000000000000000000000000000000000000 163 | ``` 164 | 165 | ## Extending PCRs 166 | This is how you add information to a PCR. 167 | First, let's check the contents of the PCR: 168 | 169 | ```bash 170 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:23 171 | sha1: 172 | 23: 0x0000000000000000000000000000000000000000 173 | ``` 174 | 175 | We can extend with a random hash 176 | ```bash 177 | [fedora@vm021273 ~]$ tpm2_pcrextend 23:sha1=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 178 | ``` 179 | 180 | After extending, we can see that the PCR contents have changed. 181 | ```bash 182 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:23 183 | sha1: 184 | 23: 0x3D96EFE6E4A9ECB1270DF4D80DEDD5062B831B5A 185 | ``` 186 | 187 | Note that the contents of the PCR are not exactly the hash we extended, this is because we cannot write directly to the PCR, instead the PCR contents will be the result of concatenating the existing value with the new value and hashing it. 188 | In this case: 189 | ``` 190 | PCR23 = hash(0x0000000000000000000000000000000000000000, 0xf1d2d2f924e986ac86fdf7b36c94bcdf32beec15) 191 | ``` 192 | 193 | The `hash` function will depend on the bank being extended. 194 | For this case it will be: sha1, sha256, sha384 and sha512. 195 | In some TPMs only the sha1 and sha256 banks are available. 196 | 197 | 198 | ## Resetting a PCR 199 | 200 | Only PCR 23 (and sometimes 16) can be reset. 201 | The rest of the PCRs are only resettable on reboot. 202 | This is to prevent a malicious entity from resettting the PCRs that store firmware and boot time measurements and storing fake measurements to trick a verifier into believing the platform is in a good state even though it's not. 203 | 204 | Let's check what's on PCR 23: 205 | ```bash 206 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:23 207 | sha1: 208 | 23: 0x3D96EFE6E4A9ECB1270DF4D80DEDD5062B831B5A 209 | ``` 210 | 211 | Now, after reset, PCR 23 is emtpy again. 212 | 213 | ```bash 214 | [fedora@vm021273 ~]$ tpm2_pcrreset 23 215 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:23 216 | sha1: 217 | 23: 0x0000000000000000000000000000000000000000 218 | ``` 219 | 220 | If we try resetting a different PCR, there will be an error and the PCR won't be reset: 221 | ```bash 222 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:2 223 | sha1: 224 | 2 : 0x86FA03B9C721AF57DE8FB1C43CC3FE7B0A42239A 225 | [fedora@vm021273 ~]$ tpm2_pcrreset 2 226 | WARNING:esys:src/tss2-esys/api/Esys_PCR_Reset.c:283:Esys_PCR_Reset_Finish() Received TPM Error 227 | ERROR:esys:src/tss2-esys/api/Esys_PCR_Reset.c:98:Esys_PCR_Reset() Esys Finish ErrorCode (0x00000907) 228 | ERROR: Could not reset PCR index: 2 229 | ERROR: Esys_PCR_Reset(0x907) - tpm:warn(2.0): bad locality 230 | ERROR: Unable to run tpm2_pcrreset 231 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:2 232 | sha1: 233 | 2 : 0x86FA03B9C721AF57DE8FB1C43CC3FE7B0A42239A 234 | ``` 235 | 236 | 237 | ## PCR Events 238 | The mechanism above using `tpm2_pcrextend` is quite a raw mechanism but it does allow very fine grained control over the hash that gets written into a given PCR in a given bank. 239 | 240 | A better way is to pass a file or stream of data and then let the TPM hash it with *all* the available PCR bank algorithms. For this we use `tpm2_pcrevent`. If we are running against the IBM software TPM then we have four hashing functions and PCR banks available. If you are running against a real TPM then this might be different, typically SHA1 and SHA256 are provided only (check with `tpm2_getcap`). We'll use PCR16 just in case you're running against a real TPM, first we collect the PCR values from all the PCR banks. 241 | 242 | ```bash 243 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:16+sha256:16+sha384:16+sha512:16 244 | sha1: 245 | 16: 0x0000000000000000000000000000000000000000 246 | sha256: 247 | 16: 0x0000000000000000000000000000000000000000000000000000000000000000 248 | sha384: 249 | 16: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 250 | sha512: 251 | 16: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 252 | 253 | ``` 254 | 255 | NOTE, sha1 and sh256 are always availble so if the above fails try `tpm2_pcrread sha1:16+sha256:16`. 256 | 257 | Using the docker container in this tutorial we'll pick an important file to hash. You can pick any file you want but for sanity and speed reasons use a small text file: 258 | 259 | ```bash 260 | [fedora@vm021273 ~]$ ls -l /bin/tpmStartup.sh 261 | -rwxr-xr-x 1 root root 387 Nov 1 12:51 /bin/tpmStartup.sh 262 | ``` 263 | 264 | Now run `tpm2_pcrevent` 265 | 266 | ```bash 267 | [fedora@vm021273 ~]$ tpm2_pcrevent /bin/tpmStartup.sh 16 268 | sha1: f44e0ba9cdcd6a63e850544fb4dfaf3d591becf7 269 | sha256: 5fa292e31e72a447c139966d22c3d72c7b01770e755dcee689fe10bd254da8c2 270 | sha384: 351c6cb2a73433fba19edf789fb5cb0bd3c7237ad5dcd8bdd357d247643746731631e9b8822cd8034ec2e0ad6671fb23 271 | sha512: 508d3a099dd4f471202511a47b42454c689d425da5bcb52d81724a21a198e2c5fbdb382b3410f67709bfc429d917091b7af0eea7159abe50f54c113a935e9843 272 | [fedora@vm021273 ~]$ tpm2_pcrread sha1:16+sha256:16+sha384:16+sha512:16 273 | sha1: 274 | 16: 0x7ACFF280464A490D5368FFFA81D296F7BB3F599C 275 | sha256: 276 | 16: 0x9596564B3949ED1C0B8935035854713489ABC1C0FD41EB265BCBE3E8E87DC24B 277 | sha384: 278 | 16: 0x2BD9E7CB6D0B74856CF756FE4B31A8FA8502BA2748D2D8CD579FE4967567C967622DE743C78951DE5F3AAEF47513477B 279 | sha512: 280 | 16: 0x961B8A10F1F5E0871C6B67A6FFDCAE9E2C7E583A8EE8B135147FD20E6508F227A721688CBBDAFC58484A34B51894F70886D327C686ECF4D16332EE1108267F2A 281 | 282 | ```` 283 | 284 | The command shows which algorithms were run and what the hash of the input was. Note how the PCR is extended. You can use `tpm2_pcrreset` to reset these and try again, for example: 285 | 286 | ```bash 287 | ~ # tpm2_pcrreset 16 288 | ~ # tpm2_pcrread sha1:16+sha256:16+sha384:16+sha512:16 289 | sha1: 290 | 16: 0x0000000000000000000000000000000000000000 291 | sha256: 292 | 16: 0x0000000000000000000000000000000000000000000000000000000000000000 293 | sha384: 294 | 16: 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 295 | sha512: 296 | 16: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 297 | ~ # tpm2_pcrevent /bin/tpmStartup.sh 16 298 | sha1: f44e0ba9cdcd6a63e850544fb4dfaf3d591becf7 299 | sha256: 5fa292e31e72a447c139966d22c3d72c7b01770e755dcee689fe10bd254da8c2 300 | sha384: 351c6cb2a73433fba19edf789fb5cb0bd3c7237ad5dcd8bdd357d247643746731631e9b8822cd8034ec2e0ad6671fb23 301 | sha512: 508d3a099dd4f471202511a47b42454c689d425da5bcb52d81724a21a198e2c5fbdb382b3410f67709bfc429d917091b7af0eea7159abe50f54c113a935e9843 302 | ~ # tpm2_pcrread sha1:16+sha256:16+sha384:16+sha512:16 303 | sha1: 304 | 16: 0x7ACFF280464A490D5368FFFA81D296F7BB3F599C 305 | sha256: 306 | 16: 0x9596564B3949ED1C0B8935035854713489ABC1C0FD41EB265BCBE3E8E87DC24B 307 | sha384: 308 | 16: 0x2BD9E7CB6D0B74856CF756FE4B31A8FA8502BA2748D2D8CD579FE4967567C967622DE743C78951DE5F3AAEF47513477B 309 | sha512: 310 | 16: 0x961B8A10F1F5E0871C6B67A6FFDCAE9E2C7E583A8EE8B135147FD20E6508F227A721688CBBDAFC58484A34B51894F70886D327C686ECF4D16332EE1108267F2A 311 | ~ # tpm2_pcrevent /bin/tpmStartup.sh 16 312 | sha1: f44e0ba9cdcd6a63e850544fb4dfaf3d591becf7 313 | sha256: 5fa292e31e72a447c139966d22c3d72c7b01770e755dcee689fe10bd254da8c2 314 | sha384: 351c6cb2a73433fba19edf789fb5cb0bd3c7237ad5dcd8bdd357d247643746731631e9b8822cd8034ec2e0ad6671fb23 315 | sha512: 508d3a099dd4f471202511a47b42454c689d425da5bcb52d81724a21a198e2c5fbdb382b3410f67709bfc429d917091b7af0eea7159abe50f54c113a935e9843 316 | ~ # tpm2_pcrread sha1:16+sha256:16+sha384:16+sha512:16 317 | sha1: 318 | 16: 0x6EFE9501AB33F915D4429E3C3BE0D305CA6C40B5 319 | sha256: 320 | 16: 0xA76D012EC62F86B8365FFD39ED2BD69A906B7163ACC7A11FDD4613FD4839626D 321 | sha384: 322 | 16: 0x6D41DD4842F64B9DCCBD45C158D45C64F476B92209404A4F20683D022CDFCED0E7DEEDE4B59B1402FE3833301DF47248 323 | sha512: 324 | 16: 0x096F662562CA918C9333E9835940693E1B2DAC2F0DBC44398BB3A24A0F669B4358C0FA2E4234D4C95D3040EFCDF41FFF6A181BDE85A2980743226ADE134E5B8E 325 | 326 | ``` 327 | 328 | 329 | -------------------------------------------------------------------------------- /docs/quoting.md: -------------------------------------------------------------------------------- 1 | # Quoting 2 | 3 | When a machine boots, the state of that machine (hashes of firmware, bootloader, kernel, etc) is stored in the PCRs. 4 | 5 | To determine if a machine is trusted, we ask the machine to report its measurements and we compare them to stored reference values. 6 | 7 | The process of requesting the measurements from the TPM of a machine is called *quoting*. 8 | 9 | We can request a quote for a set of PCRs and the TPM will return a structure called TPMS_ATTEST. 10 | We use the following command to get a quote from the TPM: 11 | 12 | ```bash 13 | [fedora@localhost ~]$ tpm2_quote -c 0x81010003 -l sha1:0,1,2,3,4,5,6,7,8,9 -m quote.msg -s quote.sig -g sha256 -q 123456 -o pcrs.out 14 | ``` 15 | 16 | This command asks the TPM to produce a quote structure (`TPMS_ATTEST`) which includes a summary of the requested measurements of the platform. 17 | This means that we can request the measurements for a specific set of PCRs (e.g. 1, 2 and 3) and the quote will include a hash over the values in those registers. 18 | This value is a summary of the requested registers because any change in any of the registers will change the output of the hash. 19 | This summary value is called *attested value*. 20 | 21 | For example, this is how an attested value for a set of PCRs 0-2 would be built: 22 | ``` 23 | pcrs: 24 | sha1: 25 | 0 : 0x7EBA0CFB74F41FEBCCDD1251F02BC208052B6023 26 | 1 : 0xB8720B5234E2F08CFA87069F172CBB43F0F08225 27 | 2 : 0x86FA03B9C721AF57DE8FB1C43CC3FE7B0A42239A 28 | ``` 29 | 30 | ``` 31 | attested_value = sha256(pcr0 || pcr1 || pcr2) 32 | attested_value = sha256( 7EBA0CFB74F41FEBCCDD1251F02BC208052B6023 || B8720B5234E2F08CFA87069F172CBB43F0F08225 || 86FA03B9C721AF57DE8FB1C43CC3FE7B0A42239A ) 33 | attested_value = 54731a1a4664db0dccf8b7c0723f4bf30cd93ffce18c4e4a63e7b8776908007a 34 | ``` 35 | This can be verified, one way to do it: 36 | ```python 37 | Python 2.7.17 (default, Nov 7 2019, 10:07:09) 38 | [GCC 7.4.0] on linux2 39 | Type "help", "copyright", "credits" or "license" for more information. 40 | >>> import hashlib 41 | >>> hash = hashlib.sha256("7EBA0CFB74F41FEBCCDD1251F02BC208052B6023B8720B5234E2F08CFA87069F172CBB43F0F0822586FA03B9C721AF57DE8FB1C43CC3FE7B0A42239A".decode("hex")) 42 | >>> hash.hexdigest() 43 | '54731a1a4664db0dccf8b7c0723f4bf30cd93ffce18c4e4a63e7b8776908007a' 44 | ``` 45 | 46 | We used the following options for the command. 47 | 48 | * `-c 0x81010003` tells the TPM to use this handle (AK) to sign the generated quote. 49 | * `-l sha1:0,1,2,3,4,5,6,7,8,9` tells the TPM to include PCRs 0-9 of the SHA1 bank in the quote. 50 | * `-m quote.msg` tells the tools to store the quote structure in `quote.msg` file. 51 | * `-s quote.sig` tells the tools to store the signature for the quote in the `quote.sig` file. 52 | * `-g sha256` tells the TPM to use the `SHA256` algorithm. 53 | * `-q 123456` tells the TPM to use `123456` as a nonce (to prevent replay attacks.) 54 | * `-o pcrs.out` stores a record of the values of the PCRs indicated with the `-l` option in the file `pcrs.out`. 55 | 56 | and this is what the output looks like: 57 | 58 | ```bash 59 | [fedora@localhost ~]$ tpm2_quote -c 0x81010003 -l sha1:0,1,2,3,4,5,6,7,8,9 -m quote.msg -s quote.sig -g sha256 -q 123456 -o pcrs.out 60 | quoted: ff54434780180022000b36ec8291b370f278c241fe44260da8b24f7bc472879d13c4888017643de294080003123456000000000007b15e000000010000000001201706190016363600000001000403ff03000020900e54b2767b470bf08fb69a1270723a6e2b0f44c661bce7b4a89244a077f9cb 61 | signature: 62 | alg: rsassa 63 | sig: 418beea652767313f9d32ec4df7f311015d7d18075d1dd58ef992de4a3a9d1eb3947a34ff8f419cc82df51003e8597e079debcf12debd512d47ac6fe95855e508ea5cbe1f4e32d90a7bf56a4ab561d82108ef8523518f9cd8dd90493815ac1ce3afcfbc1b74f81222f74c4fbf414d423175ded3c5e6db929d77d04d83f282a01e49abce38485e1f92ce847f0a3408e4399d1a1649f7aaea8375e99bbee4fd243216630bfa6afc6d06ba942ed84c59f98bf6f5abdfbf4fb7787a6de32ad23e441e32726916e670745036494466b2c12c2769923c2e99728509a5aa8938e8a2a5327b3714f6f7d82d69e8a499abed6898ac69809ff453224c61dd83714cf5fa55d 64 | pcrs: 65 | sha1: 66 | 0 : 0x7EBA0CFB74F41FEBCCDD1251F02BC208052B6023 67 | 1 : 0xB8720B5234E2F08CFA87069F172CBB43F0F08225 68 | 2 : 0x86FA03B9C721AF57DE8FB1C43CC3FE7B0A42239A 69 | 3 : 0xB2A83B0EBF2F8374299A5B2BDFC31EA955AD7236 70 | 4 : 0xAB705AAE41789E02A1909B2CBB8BFC0806115004 71 | 5 : 0x7B25D2EABBA18DC910E724A0C75020F1FEC80BE2 72 | 6 : 0xB2A83B0EBF2F8374299A5B2BDFC31EA955AD7236 73 | 7 : 0x518BD167271FBB64589C61E43D8C0165861431D8 74 | 8 : 0xC3DF1A5D37AC51163C63320F28B9C1C1FD933BD2 75 | 9 : 0x944C3EFEB668CB217B260F7D4B594DA4341E6FF2 76 | calcDigest: 900e54b2767b470bf08fb69a1270723a6e2b0f44c661bce7b4a89244a077f9cb 77 | ``` 78 | 79 | The quote structure contains other interesting fields apart from the `attested` value. 80 | It includes: 81 | * The nonce used with option `-q` (if used) 82 | * A clock value 83 | * A reset counter (number of times the machine has been rebooted) 84 | * A restart counter (number of times the machine has been suspended or hibernated) 85 | * A safe value which indicates whether the clock value is valid 86 | * Firmware version of the TPM 87 | * Information about the key used to sign the quote 88 | 89 | We can decode those fields with the following command: 90 | ```bash 91 | [fedora@localhost ~]$ tpm2_print -t TPMS_ATTEST quote.msg 92 | magic: ff544347 93 | type: 8018 94 | qualifiedSigner: 000b36ec8291b370f278c241fe44260da8b24f7bc472879d13c4888017643de29408 95 | extraData: 123456 96 | clockInfo: 97 | clock: 504158 98 | resetCount: 1 99 | restartCount: 0 100 | safe: 1 101 | firmwareVersion: 2017061900163636 102 | attested: 103 | quote: 104 | pcrSelect: 105 | count: 1 106 | pcrSelections: 107 | 0: 108 | hash: 4 (sha1) 109 | sizeofSelect: 3 110 | pcrSelect: ff0300 111 | pcrDigest: 900e54b2767b470bf08fb69a1270723a6e2b0f44c661bce7b4a89244a077f9cb 112 | ``` 113 | -------------------------------------------------------------------------------- /docs/random.md: -------------------------------------------------------------------------------- 1 | # Random Numbers 2 | - [Random Numbers](#random-numbers) 3 | - [Random Number in Raw Format](#random-number-in-raw-format) 4 | - [Random Number is Hexadecimal](#random-number-is-hexadecimal) 5 | - [Additional Randomness](#additional-randomness) 6 | 7 | The simplest command to use with a TPM is one to obtain random numbers from the onboard hardware random number generator. This command is a useful one as you can always use it to test if your TPM is working. 8 | 9 | The TPM can return a limited number of bytes at a time, typically between 1 and 32, though this might vary by manufacturer. 10 | 11 | ## Random Number in Raw Format 12 | The command `tpm2_getrandom` accepts an integer as input and returns that amount of random bytes. 13 | 14 | The minimum number of bytes to return is 1 15 | 16 | The maximum number of bytes to return may vary. Typically 32 or 64 might be the upper limit - this depends upon how the manufacturer has built their TPM. 17 | 18 | ```bash 19 | $ tpm2_getrandom 20 20 | � 21 | h�HU��ns�4�y�' 22 | ``` 23 | 24 | Note: the value returned above *is* random so what you get back should be different - the more you return the greater the probability. 25 | 26 | ## Random Number is Hexadecimal 27 | To return the bytes in hexadecimal format include the option `--hex` 28 | 29 | ```bash 30 | $ tpm2_getrandom 20 --hex 31 | 01654e15b23415b029c8cdc0085ac7f146c5a1c6 32 | ``` 33 | 34 | 35 | ## Additional Randomness 36 | The TPM has an operation to add more entropy to the random number generator. 37 | 38 | The command `tpm2_stirrandom` takes up to 128 bytes from a file or piped in from stdin to achieve this. Some examples below of two mechanisms: 39 | 40 | ```bash 41 | $ echo -n "myrandomdata" | tpm2_stirrandom 42 | $ dd if=/dev/urandom bs=1 count=64 > myrandom.bin 43 | $ tpm2_stirrandom < ./myrandom.bin 44 | ``` 45 | -------------------------------------------------------------------------------- /src/gotpm_quote.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "reflect" 7 | 8 | "github.com/google/go-tpm/tpm2" 9 | "github.com/google/go-tpm/tpmutil" 10 | ) 11 | 12 | 13 | var ( 14 | tpmPath = flag.String("tpm-path", "/dev/tpm0", "Path to the TPM device (character device or a Unix socket)") 15 | ) 16 | 17 | func main() { 18 | 19 | rwc, err := tpm2.OpenTPM(*tpmPath) 20 | if err != nil { 21 | fmt.Errorf("can't open TPM at %v", err) 22 | } 23 | //defer rwc.Close() 24 | 25 | nonce := []byte{1, 2, 3, 4, 5, 6, 7, 8} 26 | 27 | var handle = tpmutil.Handle(0x810100AA) 28 | 29 | fmt.Println("Handle is",handle) 30 | fmt.Println("Type:",reflect.TypeOf(handle).String()) 31 | 32 | // quote retuns 3 values, att, sig, err 33 | att, sig, err := tpm2.Quote( 34 | rwc, 35 | handle, 36 | "", 37 | "", 38 | nonce, 39 | tpm2.PCRSelection{ tpm2.AlgSHA256 , []int{0} }, 40 | tpm2.AlgNull) 41 | 42 | if err != nil { 43 | fmt.Errorf("Problem getting quote %s", err) 44 | fmt.Println(err) 45 | } 46 | if sig != nil { 47 | fmt.Errorf("Sig is nil\n") 48 | } 49 | if att != nil { 50 | fmt.Errorf("Att is nil\n") 51 | } 52 | // att is of type []byte 53 | // sig is of type tpm2.Signature ?? 54 | // err is ?? 55 | fmt.Println("Err is *",err,"*") 56 | fmt.Println("length ",len(att)) 57 | fmt.Println("Att [% x] ",att) 58 | 59 | 60 | } 61 | --------------------------------------------------------------------------------