mirror of https://github.com/wolfSSL/wolfBoot.git
Support for sealing/unseal a secret based on an externally signed PCR policy.
* Added new `WOLFBOOT_TPM_SEAL` and `WOLFBOOT_TPM_SEAL_NV_BASE` config options. * Added new `tools/tpm/policy_create` tool for assisting with creation of a policy digest. The sign keytool `--policy=file` signs the policy. * Added new `WOLFBOOT_TPM_VERIFY` option to enable offloading of the asymmetric verification to the TPM. By default wolfCrypt will be used. * Added example seal/unseal to update_flash for ARCH_SIM. * Renamed `WOLFBOOT_TPM_KEYSTORE_NV_INDEX` to `WOLFBOOT_TPM_KEYSTORE_NV_BASE` to support multiple public keys. * Refactored most TPM code into tpm.c. * Refactored the keystore ROT to use new `wolfBoot_check_rot` API. * Refactored the sign keytool to have a sign_digest function to allow signing firmware and policy for sealing/unsealing. * Fix for make distclean && make using the wrong key tools.pull/366/head
parent
f55a27c62f
commit
490286be7d
|
@ -53,9 +53,10 @@ jobs:
|
|||
run: |
|
||||
make -C tools/keytools && make -C tools/bin-assemble
|
||||
|
||||
- name: Build wolfboot
|
||||
# needed for tpm tools
|
||||
- name: Build keystore.c
|
||||
run: |
|
||||
make ${{inputs.make-args}} WOLFBOOT_TPM_KEYSTORE_AUTH="${{inputs.authstr}}"
|
||||
make keys ${{inputs.make-args}}
|
||||
|
||||
- name: Build TPM tools
|
||||
run: |
|
||||
|
@ -65,6 +66,16 @@ jobs:
|
|||
run: |
|
||||
./tools/tpm/rot -write ${{inputs.rot-args}} -auth="${{inputs.authstr}}"
|
||||
|
||||
- name: Create a PCR Policy
|
||||
run: |
|
||||
echo aaa > aaa.bin
|
||||
./tools/tpm/pcr_extend 0 aaa.bin
|
||||
./tools/tpm/policy_create -pcr=0 -out=policy.bin
|
||||
|
||||
- name: Build wolfboot
|
||||
run: |
|
||||
make ${{inputs.make-args}} WOLFBOOT_TPM_KEYSTORE_AUTH="${{inputs.authstr}}"
|
||||
|
||||
- name: Run wolfBoot
|
||||
run: |
|
||||
./wolfboot.elf get_version
|
||||
|
|
|
@ -36,6 +36,7 @@ jobs:
|
|||
config-file: ./config/examples/sim-tpm.config
|
||||
make-args: SIGN=RSA2048 HASH=SHA256
|
||||
|
||||
|
||||
sim_tpm_measured_ecc256:
|
||||
uses: ./.github/workflows/test-build-sim-tpm.yml
|
||||
with:
|
||||
|
@ -82,3 +83,29 @@ jobs:
|
|||
config-file: ./config/examples/sim-tpm-keystore.config
|
||||
make-args: SIGN=RSA2048 HASH=SHA256
|
||||
authstr: TestAuth
|
||||
|
||||
|
||||
sim_tpm_seal_ecc256:
|
||||
uses: ./.github/workflows/test-build-sim-tpm.yml
|
||||
with:
|
||||
arch: host
|
||||
config-file: ./config/examples/sim-tpm-seal.config
|
||||
make-args: SIGN=ECC256 HASH=SHA256 POLICY_FILE=policy.bin
|
||||
authstr: TestAuth
|
||||
|
||||
sim_tpm_seal_ecc384:
|
||||
uses: ./.github/workflows/test-build-sim-tpm.yml
|
||||
with:
|
||||
arch: host
|
||||
config-file: ./config/examples/sim-tpm-seal.config
|
||||
make-args: SIGN=ECC384 HASH=SHA384 POLICY_FILE=policy.bin
|
||||
rot-args: -sha384
|
||||
authstr: TestAuth
|
||||
|
||||
sim_tpm_seal_rsa2048:
|
||||
uses: ./.github/workflows/test-build-sim-tpm.yml
|
||||
with:
|
||||
arch: host
|
||||
config-file: ./config/examples/sim-tpm-seal.config
|
||||
make-args: SIGN=RSA2048 HASH=SHA256 POLICY_FILE=policy.bin
|
||||
authstr: TestAuth
|
||||
|
|
|
@ -101,6 +101,10 @@ tools/unit-tests/unit-parser
|
|||
tools/bin-assemble/bin-assemble
|
||||
tools/elf-parser/elf-parser
|
||||
tools/tpm/rot
|
||||
tools/tpm/pcr_read
|
||||
tools/tpm/pcr_reset
|
||||
tools/tpm/pcr_extend
|
||||
tools/tpm/policy_create
|
||||
config/*.ld
|
||||
|
||||
# Generated confiuguration file
|
||||
|
|
|
@ -37,7 +37,8 @@ Note: If not using Position Independent Code (PIC) the linker script `ldscript.l
|
|||
## Signing Example
|
||||
|
||||
```sh
|
||||
python3 ./tools/keytools/sign.py --rsa4096 --sha3 ../helloworld/Debug/helloworld.elf ./rsa4096.der 1
|
||||
make keytools
|
||||
./tools/keytools/sign --rsa4096 --sha3 ../helloworld/Debug/helloworld.elf ./rsa4096.der 1
|
||||
```
|
||||
|
||||
## Bootgen
|
||||
|
|
2
Makefile
2
Makefile
|
@ -154,10 +154,8 @@ include tools/test-enc.mk
|
|||
include tools/test-delta.mk
|
||||
include tools/test-renode.mk
|
||||
|
||||
PYTHON?=python3
|
||||
keytools_check: keytools FORCE
|
||||
|
||||
|
||||
$(PRIVATE_KEY):
|
||||
$(Q)$(MAKE) keytools_check
|
||||
$(Q)(test $(SIGN) = NONE) || ("$(KEYGEN_TOOL)" $(KEYGEN_OPTIONS) -g $(PRIVATE_KEY)) || true
|
||||
|
|
|
@ -19,7 +19,7 @@ WOLFBOOT_FIXED_PARTITIONS=1
|
|||
|
||||
# Use NV for TPM based Root of Trust
|
||||
WOLFBOOT_TPM_KEYSTORE?=1
|
||||
WOLFBOOT_TPM_KEYSTORE_NV_INDEX?=0x01400200
|
||||
WOLFBOOT_TPM_KEYSTORE_NV_BASE?=0x01400200
|
||||
#WOLFBOOT_TPM_KEYSTORE_AUTH?=TestAuth
|
||||
|
||||
# TPM Logging
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
ARCH=sim
|
||||
TARGET=sim
|
||||
SIGN?=ECC256
|
||||
HASH?=SHA256
|
||||
SPI_FLASH=0
|
||||
DEBUG=0
|
||||
WOLFTPM=1
|
||||
|
||||
# sizes should be multiple of system page size
|
||||
WOLFBOOT_PARTITION_SIZE=0x40000
|
||||
WOLFBOOT_SECTOR_SIZE=0x1000
|
||||
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80000
|
||||
# if on external flash, it should be multiple of system page size
|
||||
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x100000
|
||||
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x180000
|
||||
|
||||
# required for keytools
|
||||
WOLFBOOT_FIXED_PARTITIONS=1
|
||||
|
||||
# Use NV for TPM based Root of Trust
|
||||
WOLFBOOT_TPM_KEYSTORE?=1
|
||||
WOLFBOOT_TPM_KEYSTORE_NV_BASE?=0x01400200
|
||||
#WOLFBOOT_TPM_KEYSTORE_AUTH?=TestAuth
|
||||
|
||||
# Measured boot at test PCR index 16
|
||||
MEASURED_BOOT?=1
|
||||
MEASURED_PCR_A?=16
|
||||
|
||||
# Sealing a secret into TPM based on external PCR policy signed by the sign tool
|
||||
WOLFBOOT_TPM_SEAL?=1
|
||||
WOLFBOOT_TPM_SEAL_NV_BASE=0x01400300
|
||||
|
||||
# TPM Logging
|
||||
#CFLAGS_EXTRA+=-DDEBUG_WOLFTPM
|
||||
#CFLAGS_EXTRA+=-DWOLFTPM_DEBUG_VERBOSE
|
|
@ -5,6 +5,8 @@ HASH?=SHA256
|
|||
SPI_FLASH=0
|
||||
DEBUG=0
|
||||
WOLFTPM=1
|
||||
# enable offloading of asymmetric verify to TPM
|
||||
WOLFBOOT_TPM_VERIFY?=1
|
||||
|
||||
# sizes should be multiple of system page size
|
||||
WOLFBOOT_PARTITION_SIZE=0x40000
|
||||
|
|
|
@ -13,7 +13,7 @@ WOLFTPM=0
|
|||
|
||||
# TPM Keystore options
|
||||
#WOLFBOOT_TPM_KEYSTORE?=1
|
||||
#WOLFBOOT_TPM_KEYSTORE_NV_INDEX?=0x01800200
|
||||
#WOLFBOOT_TPM_KEYSTORE_NV_BASE?=0x01800200
|
||||
#WOLFBOOT_TPM_POLICY_NV_INDEX?=0x01800201
|
||||
|
||||
# 4gb - 8mb
|
||||
|
|
|
@ -13,7 +13,7 @@ WOLFTPM=0
|
|||
|
||||
# TPM Keystore options
|
||||
#WOLFBOOT_TPM_KEYSTORE?=1
|
||||
#WOLFBOOT_TPM_KEYSTORE_NV_INDEX?=0x01800200
|
||||
#WOLFBOOT_TPM_KEYSTORE_NV_BASE?=0x01800200
|
||||
#WOLFBOOT_TPM_POLICY_NV_INDEX?=0x01800201
|
||||
|
||||
# 4gb - 8mb
|
||||
|
|
|
@ -13,7 +13,7 @@ WOLFTPM=1
|
|||
|
||||
# TPM Keystore options
|
||||
#WOLFBOOT_TPM_KEYSTORE?=1
|
||||
#WOLFBOOT_TPM_KEYSTORE_NV_INDEX?=0x01800200
|
||||
#WOLFBOOT_TPM_KEYSTORE_NV_BASE?=0x01800200
|
||||
#WOLFBOOT_TPM_POLICY_NV_INDEX?=0x01800201
|
||||
|
||||
# 4gb - 8mb
|
||||
|
|
|
@ -13,7 +13,7 @@ WOLFTPM=1
|
|||
|
||||
# TPM Keystore options
|
||||
WOLFBOOT_TPM_KEYSTORE?=1
|
||||
WOLFBOOT_TPM_KEYSTORE_NV_INDEX?=0x01800200
|
||||
WOLFBOOT_TPM_KEYSTORE_NV_BASE?=0x01800200
|
||||
WOLFBOOT_TPM_POLICY_NV_INDEX?=0x01800201
|
||||
|
||||
# 4gb - 8mb
|
||||
|
|
|
@ -157,7 +157,6 @@ be used for the key, 16 for the initialization of the IV.
|
|||
SHAREDKEY.BIN is expected to be exactly 48 bytes in size, of which 32 will
|
||||
be used for the key, 16 for the initialization of the IV.
|
||||
|
||||
|
||||
#### Delta updates (incremental updates from a known version)
|
||||
|
||||
An incremental update is created using the sign tool when the following option
|
||||
|
@ -167,6 +166,16 @@ is provided:
|
|||
`BASE_SIGNED_IMG.BIN` and the new image signed starting from `IMAGE.BIN`. The
|
||||
result is stored in a file ending in `_signed_diff.bin`.
|
||||
|
||||
#### Policy signing (for sealing/unsealing with a TPM)
|
||||
|
||||
Provides a PCR mask and digest to be signed and included in the header. The signing key is used to sign the digest.
|
||||
|
||||
* `--policy policy.bin`: This argument is multi-purpose.
|
||||
By default the file should contain a 4-byte PCR mask and SHA2-256 PCR digest to be signed.
|
||||
If using `--manual-sign` then the file should contain the 4-byte PCR mask and signature.
|
||||
The PCR mask and signature will be included in the `HDR_POLICY_SIGNATURE` header tag.
|
||||
Note: This may require increasing the `IMAGE_HEADER_SIZE` as two signatures will be stored in the header.
|
||||
|
||||
#### Three-steps signing using external provisioning tools
|
||||
|
||||
If the private key is not accessible, while it's possible to sign payloads using
|
||||
|
|
143
docs/TPM.md
143
docs/TPM.md
|
@ -6,11 +6,14 @@ In wolfBoot we support TPM based root of trust, sealing/unsealing, cryptographic
|
|||
|
||||
| Config Option | Preprocessor Macro | Description |
|
||||
| ------------- | ------------------ | ----------------------------------- |
|
||||
| `WOLFTPM=1` | `WOLFBOOT_TPM` | Enables wolfTPM support and cryptographic offloading for RSA2048 and ECC256/384 |
|
||||
| `WOLFTPM=1` | `WOLFBOOT_TPM` | Enables wolfTPM support |
|
||||
| `WOLFBOOT_TPM_VERIFY=1` | `WOLFBOOT_TPM_VERIFY` | Enables cryptographic offloading for RSA2048 and ECC256/384 to the TPM. |
|
||||
| `WOLFBOOT_TPM_KEYSTORE=1` | `WOLFBOOT_TPM_KEYSTORE` | Enables TPM based root of trust. NV Index must store a hash of the trusted public key. |
|
||||
| `WOLFBOOT_TPM_KEYSTORE_NV_INDEX=0x` | `WOLFBOOT_TPM_KEYSTORE_NV_INDEX=0x` | NV index in platform range 0x1400000 - 0x17FFFFF |
|
||||
| `WOLFBOOT_TPM_KEYSTORE_NV_BASE=0x` | `WOLFBOOT_TPM_KEYSTORE_NV_BASE=0x` | NV index in platform range 0x1400000 - 0x17FFFFF. |
|
||||
| `MEASURED_BOOT=1` | `WOLFBOOT_MEASURED_BOOT` | Enable measured boot. Extend PCR with wolfBoot hash. |
|
||||
| `MEASURED_PCR_A=16` | `WOLFBOOT_MEASURED_PCR_A=16` | The PCR index to use. See [docs/measured_boot.md](/docs/measured_boot.md) |
|
||||
| `MEASURED_PCR_A=16` | `WOLFBOOT_MEASURED_PCR_A=16` | The PCR index to use. See [docs/measured_boot.md](/docs/measured_boot.md). |
|
||||
| `WOLFBOOT_TPM_SEAL=1` | `WOLFBOOT_TPM_SEAL` | Enables support for sealing/unsealing based on PCR policy signed externally. |
|
||||
| `WOLFBOOT_TPM_SEAL_NV_BASE=0x01400300` | `WOLFBOOT_TPM_SEAL_NV_BASE` | To override the default sealed blob storage location in the platform hierarchy. |
|
||||
|
||||
## Root of Trust (ROT)
|
||||
|
||||
|
@ -20,12 +23,140 @@ The design uses a platform NV handle that has been locked. The NV stores a hash
|
|||
|
||||
## Cryptographic offloading
|
||||
|
||||
The RSA2048 and ECC256/384 bit verification can be offloaded to a TPM for code size reduction or performance improvement.
|
||||
The RSA2048 and ECC256/384 bit verification can be offloaded to a TPM for code size reduction or performance improvement. Enabled using `WOLFBOOT_TPM_VERIFY`
|
||||
|
||||
## Measured Boot
|
||||
|
||||
The wolfBoot image is hashed and extended to the indicated PCR. This can be used later in the application to prove the boot process was not tampered with.
|
||||
The wolfBoot image is hashed and extended to the indicated PCR. This can be used later in the application to prove the boot process was not tampered with. Enabled with `WOLFBOOT_MEASURED_BOOT` and exposes API `wolfBoot_tpm2_extend`.
|
||||
|
||||
## Sealing and Unsealing a secret
|
||||
|
||||
API's for this will be available soon.
|
||||
See the wolfTPM Sealing/Unsealing example [here](https://github.com/wolfSSL/wolfTPM/tree/secret_seal/examples/boot#secure-boot-encryption-key-storage)
|
||||
|
||||
Known PCR values must be signed to seal/unseal a secret. The signature for the authorization policy resides in the signed header using the `--policy` argument.
|
||||
If a signed policy is not in the header then a value cannot be sealed. Instead the PCR(s) and a digest to sign will be printed for use with the sign tool.
|
||||
|
||||
This exposes two new wolfBoot API's for sealing and unsealing data with blob stored to NV index:
|
||||
```c
|
||||
int wolfBoot_seal(struct wolfBoot_image* img, int index, const uint8_t* secret, int secret_sz);
|
||||
int wolfBoot_unseal(struct wolfBoot_image* img, int index, uint8_t* secret, int* secret_sz);
|
||||
```
|
||||
|
||||
By default this index will be based on an NV Index at `(0x01400300 + index)`.
|
||||
The default NV base can be overridden with `WOLFBOOT_TPM_SEAL_NV_BASE`.
|
||||
|
||||
|
||||
### Testing seal/unseal with simulator
|
||||
|
||||
```sh
|
||||
cp config/examples/sim-tpm-seal.config .config
|
||||
make keytools
|
||||
make tpmtools
|
||||
echo aaa > aaa.bin
|
||||
./tools/tpm/pcr_extend 0 aaa.bin
|
||||
./tools/tpm/policy_create -pcr=0
|
||||
# if ROT enabled
|
||||
./tools/tpm/rot -write
|
||||
make clean && make POLICY_FILE=policy.bin
|
||||
./wolfboot.elf get_version
|
||||
Simulator assigned ./internal_flash.dd to base 0x103797000
|
||||
Mfg IBM (0), Vendor SW TPM, Fw 8217.4131 (0x163636), FIPS 140-2 1, CC-EAL4 0
|
||||
Unlocking disk...
|
||||
Boot partition: 0x103817000
|
||||
Image size 54400
|
||||
Sealing 32 bytes
|
||||
11c6ac0ec972ae567c541750c6ecccd426f131dad3eeca5e6540d901d9f0c336
|
||||
Unsealed 32 bytes
|
||||
11c6ac0ec972ae567c541750c6ecccd426f131dad3eeca5e6540d901d9f0c336
|
||||
Boot partition: 0x103817000
|
||||
Image size 54400
|
||||
TPM Root of Trust valid (id 0)
|
||||
Simulator assigned ./internal_flash.dd to base 0x103962000
|
||||
1
|
||||
```
|
||||
|
||||
### Testing seal/unseal on actual hardware
|
||||
|
||||
1) Get the actual PCR digest for policy.
|
||||
2) Sign policy and include in firmware image header.
|
||||
|
||||
|
||||
#### Getting PCR values
|
||||
|
||||
If no signed policy exists, then the seal function will generate and display the active PCR's, PCR digest and policy digest (to sign)
|
||||
|
||||
```sh
|
||||
% make tpmtools
|
||||
% ./tools/tpm/rot -write
|
||||
% ./tools/tpm/pcr_reset 16
|
||||
% ./wolfboot.elf get_version
|
||||
Simulator assigned ./internal_flash.dd to base 0x101a64000
|
||||
Mfg IBM (0), Vendor SW TPM, Fw 8217.4131 (0x163636), FIPS 140-2 1, CC-EAL4 0
|
||||
Boot partition: 0x101ae4000
|
||||
Image size 57192
|
||||
Policy header not found!
|
||||
Generating policy based on active PCR's!
|
||||
Getting active PCR's (0-16)
|
||||
PCR 16 (counter 20)
|
||||
8f7ac1d5a5eac58a2305ca459f27c35705a9212c0fb2a9088b1df761f3d5f842
|
||||
Found 1 active PCR's (mask 0x00010000)
|
||||
PCR Digest (32 bytes):
|
||||
f84085631f85333ad0338b06c82f16888b7923abaccffb881d5416e389be256c
|
||||
PCR Mask (0x00010000) and PCR Policy Digest (36 bytes):
|
||||
0000010034ba061436aba2e9a167a1ee46af4a9578a8c6b9f71fdece21607a0cb40468ec
|
||||
Use this policy with the sign tool (--policy arg) or POLICY_FILE config
|
||||
Image policy signature missing!
|
||||
Boot partition: 0x101ae4000
|
||||
Image size 57192
|
||||
TPM Root of Trust valid (id 0)
|
||||
Simulator assigned ./internal_flash.dd to base 0x101c2f000
|
||||
1
|
||||
```
|
||||
|
||||
The `0000010034ba061436aba2e9a167a1ee46af4a9578a8c6b9f71fdece21607a0cb40468ec` above can be directly used by the keytool. The
|
||||
|
||||
`echo "0000010034ba061436aba2e9a167a1ee46af4a9578a8c6b9f71fdece21607a0cb40468ec" | xxd -r -p > policy.bin`
|
||||
|
||||
OR use the `tools/tpm/policy_create` tool to generate a digest to be signed. The used PCR(s) must be set using "-pcr=#". The PCR digest can be supplied using "-pcrdigest=" or if not supplied will be read from the TPM directly.
|
||||
|
||||
```sh
|
||||
% ./tools/tpm/policy_create -pcr=16 -pcrdigest=f84085631f85333ad0338b06c82f16888b7923abaccffb881d5416e389be256c -out=policy.bin
|
||||
# OR
|
||||
% ./tools/tpm/policy_create -pcrmask=0x00010000 -pcrdigest=f84085631f85333ad0338b06c82f16888b7923abaccffb881d5416e389be256c -out=policy.bin
|
||||
Policy Create Tool
|
||||
PCR Index(s) (SHA256): 16 (mask 0x00010000)
|
||||
PCR Digest (32 bytes):
|
||||
f84085631f85333ad0338b06c82f16888b7923abaccffb881d5416e389be256c
|
||||
PCR Mask (0x00010000) and PCR Policy Digest (36 bytes):
|
||||
0000010034ba061436aba2e9a167a1ee46af4a9578a8c6b9f71fdece21607a0cb40468ec
|
||||
Wrote 36 bytes to policy.bin
|
||||
```
|
||||
|
||||
#### Signing Policy
|
||||
|
||||
Building firmware with the policy digest to sign:
|
||||
|
||||
```sh
|
||||
% make POLICY_FILE=policy.bin
|
||||
```
|
||||
|
||||
OR manually using:
|
||||
|
||||
```sh
|
||||
% ./tools/keytools/sign --ecc256 --policy policy.bin test-app/image.elf wolfboot_signing_private_key.der 1
|
||||
wolfBoot KeyTools (Compiled C version)
|
||||
wolfBoot version 1100000
|
||||
Update type: Firmware
|
||||
Input image: test-app/image.elf
|
||||
Selected cipher: ECC256
|
||||
Selected hash : SHA256
|
||||
Public key: wolfboot_signing_private_key.der
|
||||
Output image: test-app/image_v1_signed.bin
|
||||
Target partition id : 1
|
||||
image header size calculated at runtime (256 bytes)
|
||||
Calculating SHA256 digest...
|
||||
Signing the digest...
|
||||
Opening policy file policy.bin
|
||||
Signing the policy digest...
|
||||
Output image(s) successfully created.
|
||||
```
|
||||
|
|
|
@ -569,7 +569,11 @@ uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
|
|||
/* Defined in libwolfboot */
|
||||
uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr);
|
||||
|
||||
/* get header type for image */
|
||||
uint16_t wolfBoot_get_header(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr);
|
||||
|
||||
/* Find the key slot ID based on the SHA hash of the key. */
|
||||
int keyslot_id_by_sha(const uint8_t *hint);
|
||||
|
||||
#ifdef EXT_FLASH
|
||||
# ifdef PART_BOOT_EXT
|
||||
|
|
|
@ -71,11 +71,6 @@ extern "C" {
|
|||
# error "No public key available for given signing algorithm."
|
||||
#endif /* Algorithm selection */
|
||||
|
||||
#ifdef WOLFBOOT_TPM
|
||||
int wolfBoot_tpm2_init(void);
|
||||
void wolfBoot_tpm2_deinit(void);
|
||||
#endif
|
||||
|
||||
void wolfBoot_start(void);
|
||||
|
||||
#if defined(ARCH_ARM) && defined(WOLFBOOT_ARMORED)
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* tpm.h
|
||||
*
|
||||
* Copyright (C) 2023 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
*
|
||||
* wolfBoot is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfBoot is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifndef _WOLFBOOT_TPM_H_
|
||||
#define _WOLFBOOT_TPM_H_
|
||||
|
||||
#ifdef WOLFBOOT_TPM
|
||||
|
||||
#include "wolftpm/tpm2.h"
|
||||
#include "wolftpm/tpm2_wrap.h"
|
||||
|
||||
extern WOLFTPM2_DEV wolftpm_dev;
|
||||
#if defined(WOLFBOOT_TPM_KEYSTORE) || defined(WOLFBOOT_TPM_SEAL)
|
||||
extern WOLFTPM2_SESSION wolftpm_session;
|
||||
extern WOLFTPM2_KEY wolftpm_srk;
|
||||
#endif
|
||||
|
||||
#ifndef WOLFBOOT_TPM_KEYSTORE_NV_BASE
|
||||
#define WOLFBOOT_TPM_KEYSTORE_NV_BASE 0x01400200
|
||||
#endif
|
||||
#ifndef WOLFBOOT_TPM_SEAL_NV_BASE
|
||||
#define WOLFBOOT_TPM_SEAL_NV_BASE 0x01400300
|
||||
#endif
|
||||
#ifndef WOLFBOOT_TPM_PCR_ALG
|
||||
/* Prefer SHA2-256 for PCR's, and all TPM 2.0 devices support it */
|
||||
#define WOLFBOOT_TPM_PCR_ALG TPM_ALG_SHA256
|
||||
#define WOLFBOOT_TPM_PCR_DIG_SZ 32
|
||||
#endif
|
||||
|
||||
#define WOLFBOOT_MAX_SEAL_SZ MAX_SYM_DATA
|
||||
|
||||
|
||||
int wolfBoot_tpm2_init(void);
|
||||
void wolfBoot_tpm2_deinit(void);
|
||||
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||
int wolfBoot_check_rot(int key_slot, uint8_t* pubkey_hint);
|
||||
#endif
|
||||
|
||||
#ifdef WOLFBOOT_TPM_SEAL
|
||||
int wolfBoot_get_random(uint8_t* buf, int sz);
|
||||
int wolfBoot_get_pcr_active(uint8_t pcrAlg, uint32_t* pcrMask, uint8_t pcrMax);
|
||||
int wolfBoot_build_policy(uint8_t pcrAlg, uint32_t pcrMask, uint8_t* policy, uint32_t* policySz, uint8_t* policyRef, uint32_t policyRefSz);
|
||||
int wolfBoot_get_policy(struct wolfBoot_image* img, uint8_t** policy, uint16_t* policySz);
|
||||
int wolfBoot_seal(struct wolfBoot_image* img, int index, const uint8_t* secret, int secret_sz);
|
||||
int wolfBoot_seal_blob(struct wolfBoot_image* img, WOLFTPM2_KEYBLOB* seal_blob, const uint8_t* secret, int secret_sz);
|
||||
int wolfBoot_unseal(struct wolfBoot_image* img, int index, uint8_t* secret, int* secret_sz);
|
||||
int wolfBoot_unseal_blob(struct wolfBoot_image* img, WOLFTPM2_KEYBLOB* seal_blob, uint8_t* secret, int* secret_sz);
|
||||
#endif
|
||||
|
||||
#ifdef WOLFBOOT_MEASURED_BOOT
|
||||
int wolfBoot_tpm2_extend(uint8_t pcrIndex, uint8_t* hash, int line);
|
||||
|
||||
/* helper for measuring boot at line */
|
||||
#define measure_boot(hash) \
|
||||
wolfBoot_tpm2_extend(WOLFBOOT_MEASURED_PCR_A, (hash), __LINE__)
|
||||
#endif /* WOLFBOOT_MEASURED_BOOT */
|
||||
|
||||
/* debugging */
|
||||
void wolfBoot_print_hexstr(const unsigned char* bin, unsigned long sz,
|
||||
unsigned long maxLine);
|
||||
void wolfBoot_print_bin(const byte* buffer, word32 length);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* stubs */
|
||||
#define measure_boot(hash)
|
||||
|
||||
#endif /* WOLFBOOT_TPM */
|
||||
|
||||
#endif /* !_WOLFBOOT_TPM_H_ */
|
|
@ -44,6 +44,10 @@ extern int tolower(int c);
|
|||
# define WC_NO_HARDEN
|
||||
#endif
|
||||
|
||||
#if defined(WOLFBOOT_TPM_KEYSTORE) || defined(WOLFBOOT_TPM_SEAL)
|
||||
# define WOLFBOOT_TPM_PARMENC /* used in this file to gate features */
|
||||
#endif
|
||||
|
||||
/* ED25519 and SHA512 */
|
||||
#ifdef WOLFBOOT_SIGN_ED25519
|
||||
# define HAVE_ED25519
|
||||
|
@ -110,7 +114,7 @@ extern int tolower(int c);
|
|||
# define WOLFSSL_SP_384
|
||||
# define WOLFSSL_SP_NO_256
|
||||
# endif
|
||||
# if !defined(WOLFBOOT_TPM_KEYSTORE)
|
||||
# if !defined(WOLFBOOT_TPM_PARMENC)
|
||||
# define NO_ECC256
|
||||
# endif
|
||||
#elif defined(WOLFBOOT_SIGN_ECC521)
|
||||
|
@ -120,7 +124,7 @@ extern int tolower(int c);
|
|||
# define WOLFSSL_SP_521
|
||||
# define WOLFSSL_SP_NO_256
|
||||
# endif
|
||||
# if !defined(WOLFBOOT_TPM_KEYSTORE)
|
||||
# if !defined(WOLFBOOT_TPM_PARMENC)
|
||||
# define NO_ECC256
|
||||
# endif
|
||||
#endif
|
||||
|
@ -135,7 +139,7 @@ extern int tolower(int c);
|
|||
# define WOLFSSL_RSA_VERIFY_INLINE
|
||||
# define WOLFSSL_RSA_VERIFY_ONLY
|
||||
# endif
|
||||
# ifndef WOLFBOOT_TPM_KEYSTORE
|
||||
# if !defined(WOLFBOOT_TPM_PARMENC)
|
||||
# define WC_NO_RSA_OAEP
|
||||
# endif
|
||||
# define FP_MAX_BITS (2048 * 2)
|
||||
|
@ -190,14 +194,14 @@ extern int tolower(int c);
|
|||
|
||||
#ifdef WOLFBOOT_HASH_SHA3_384
|
||||
# define WOLFSSL_SHA3
|
||||
# if defined(NO_RSA) && !defined(WOLFBOOT_TPM_KEYSTORE)
|
||||
# if defined(NO_RSA) && !defined(WOLFBOOT_TPM_PARMENC)
|
||||
# define NO_SHA256
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef WOLFBOOT_HASH_SHA384
|
||||
# define WOLFSSL_SHA384
|
||||
# if defined(NO_RSA) && !defined(WOLFBOOT_TPM_KEYSTORE)
|
||||
# if defined(NO_RSA) && !defined(WOLFBOOT_TPM_PARMENC)
|
||||
# define NO_SHA256
|
||||
# endif
|
||||
#endif
|
||||
|
@ -232,8 +236,16 @@ extern int tolower(int c);
|
|||
#ifdef WOLFBOOT_TPM
|
||||
/* Do not use heap */
|
||||
#define WOLFTPM2_NO_HEAP
|
||||
/* small stack options */
|
||||
#ifdef WOLFTPM_SMALL_STACK
|
||||
#define MAX_COMMAND_SIZE 1024
|
||||
#define MAX_RESPONSE_SIZE 1350
|
||||
#define WOLFTPM2_MAX_BUFFER 1500
|
||||
#define MAX_SESSION_NUM 2
|
||||
#define MAX_DIGEST_BUFFER 973
|
||||
#endif
|
||||
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||
#ifdef WOLFBOOT_TPM_PARMENC
|
||||
/* Enable AES CFB (parameter encryption) and HMAC (for KDF) */
|
||||
#define WOLFSSL_AES_CFB
|
||||
|
||||
|
@ -241,7 +253,7 @@ extern int tolower(int c);
|
|||
#define WOLFSSL_PUBLIC_MP
|
||||
|
||||
/* Configure RNG seed */
|
||||
#define CUSTOM_RAND_GENERATE_SEED(buf, sz) 0 /* stub, not used */
|
||||
#define CUSTOM_RAND_GENERATE_SEED(buf, sz) ({(void)buf; (void)sz; 0;}) /* stub, not used */
|
||||
#define WC_RNG_SEED_CB
|
||||
#define HAVE_HASHDRBG
|
||||
#endif
|
||||
|
@ -269,10 +281,10 @@ extern int tolower(int c);
|
|||
|
||||
/* Disables - For minimum wolfCrypt build */
|
||||
#if !defined(ENCRYPT_WITH_AES128) && !defined(ENCRYPT_WITH_AES256) && \
|
||||
!defined(WOLFBOOT_TPM_KEYSTORE)
|
||||
!defined(WOLFBOOT_TPM_PARMENC)
|
||||
#define NO_AES
|
||||
#endif
|
||||
#if !defined(WOLFBOOT_TPM_KEYSTORE)
|
||||
#if !defined(WOLFBOOT_TPM_PARMENC)
|
||||
#define NO_HMAC
|
||||
#define WC_NO_RNG
|
||||
#define WC_NO_HASHDRBG
|
||||
|
|
|
@ -209,6 +209,7 @@ extern "C" {
|
|||
|
||||
#endif /* defined WOLFBOOT */
|
||||
|
||||
|
||||
#define PART_BOOT 0
|
||||
#define PART_UPDATE 1
|
||||
#define PART_SWAP 2
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 5b7e50a19c79ef51530df6f32912c60490336fb4
|
||||
Subproject commit 50bfac48a970a61afa1463ec6514bf9b404830cb
|
|
@ -1 +1 @@
|
|||
Subproject commit 05b692d01cb2fa172d8a86e04a1dbbdb5eb88703
|
||||
Subproject commit cd02d5140fccd2478dcd4845d1b7cef6be881dde
|
38
options.mk
38
options.mk
|
@ -1,3 +1,8 @@
|
|||
ifeq ($(WOLFBOOT_TPM_VERIFY),1)
|
||||
WOLFTPM:=1
|
||||
CFLAGS+=-D"WOLFBOOT_TPM_VERIFY"
|
||||
endif
|
||||
|
||||
## Measured boot requires TPM to be present
|
||||
ifeq ($(MEASURED_BOOT),1)
|
||||
WOLFTPM:=1
|
||||
|
@ -7,15 +12,28 @@ endif
|
|||
|
||||
## TPM keystore
|
||||
ifeq ($(WOLFBOOT_TPM_KEYSTORE),1)
|
||||
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/random.o
|
||||
ifneq ($(WOLFBOOT_TPM_KEYSTORE_NV_INDEX),)
|
||||
WOLFTPM:=1
|
||||
CFLAGS+=-DWOLFBOOT_TPM_KEYSTORE
|
||||
CFLAGS+=-DWOLFBOOT_TPM_KEYSTORE_NV_INDEX=$(WOLFBOOT_TPM_KEYSTORE_NV_INDEX)
|
||||
CFLAGS+=-D"WOLFBOOT_TPM_KEYSTORE"
|
||||
ifneq ($(WOLFBOOT_TPM_KEYSTORE_AUTH),)
|
||||
CFLAGS+=-DWOLFBOOT_TPM_KEYSTORE_AUTH='"$(WOLFBOOT_TPM_KEYSTORE_AUTH)"'
|
||||
endif
|
||||
ifneq ($(WOLFBOOT_TPM_KEYSTORE_NV_BASE),)
|
||||
CFLAGS+=-D"WOLFBOOT_TPM_KEYSTORE_NV_BASE=$(WOLFBOOT_TPM_KEYSTORE_NV_BASE)"
|
||||
endif
|
||||
endif
|
||||
|
||||
## Sealing a secret into the TPM
|
||||
ifeq ($(WOLFBOOT_TPM_SEAL),1)
|
||||
WOLFTPM:=1
|
||||
CFLAGS+=-D"WOLFBOOT_TPM_SEAL"
|
||||
ifneq ($(WOLFBOOT_TPM_SEAL_NV_BASE),)
|
||||
CFLAGS+=-D"WOLFBOOT_TPM_SEAL_NV_BASE=$(WOLFBOOT_TPM_SEAL_NV_BASE)"
|
||||
endif
|
||||
|
||||
ifneq ($(POLICY_FILE),)
|
||||
SIGN_OPTIONS+=--policy $(POLICY_FILE)
|
||||
endif
|
||||
endif
|
||||
|
||||
## DSA Settings
|
||||
ifeq ($(SIGN),NONE)
|
||||
|
@ -503,15 +521,16 @@ ifeq ($(WOLFBOOT_HUGE_STACK),1)
|
|||
endif
|
||||
|
||||
ifeq ($(WOLFTPM),1)
|
||||
OBJS += lib/wolfTPM/src/tpm2.o \
|
||||
OBJS+=\
|
||||
./src/tpm.o \
|
||||
lib/wolfTPM/src/tpm2.o \
|
||||
lib/wolfTPM/src/tpm2_packet.o \
|
||||
lib/wolfTPM/src/tpm2_tis.o \
|
||||
lib/wolfTPM/src/tpm2_wrap.o \
|
||||
lib/wolfTPM/src/tpm2_param_enc.o
|
||||
CFLAGS+=-D"WOLFBOOT_TPM" -D"SIZEOF_LONG=4" -Ilib/wolfTPM \
|
||||
-D"MAX_COMMAND_SIZE=1024" -D"MAX_RESPONSE_SIZE=1024" -D"WOLFTPM2_MAX_BUFFER=1500" \
|
||||
-D"MAX_SESSION_NUM=2" -D"MAX_DIGEST_BUFFER=973" \
|
||||
-D"WOLFTPM_SMALL_STACK"
|
||||
CFLAGS+=-Ilib/wolfTPM
|
||||
CFLAGS+=-D"WOLFBOOT_TPM"
|
||||
CFLAGS+=-D"WOLFTPM_SMALL_STACK"
|
||||
CFLAGS+=-D"WOLFTPM_AUTODETECT"
|
||||
ifneq ($(SPI_FLASH),1)
|
||||
# don't use spi if we're using simulator
|
||||
|
@ -534,6 +553,7 @@ ifeq ($(WOLFTPM),1)
|
|||
endif
|
||||
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/aes.o
|
||||
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/hmac.o
|
||||
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/random.o
|
||||
ifeq ($(DEBUG),1)
|
||||
CFLAGS+=-DWOLFBOOT_DEBUG_TPM=1
|
||||
endif
|
||||
|
|
503
src/image.c
503
src/image.c
|
@ -25,45 +25,24 @@
|
|||
*/
|
||||
#ifndef IMAGE_H_
|
||||
#define IMAGE_H_
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h> /* for wolfCrypt hash/sign routines */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "loader.h"
|
||||
#include "image.h"
|
||||
#include "hal.h"
|
||||
#include "spi_drv.h"
|
||||
#include <stddef.h>
|
||||
#include "printf.h"
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "image.h"
|
||||
|
||||
#ifdef WOLFBOOT_TPM
|
||||
#include <stdlib.h>
|
||||
#include "wolftpm/tpm2.h"
|
||||
#include "wolftpm/tpm2_wrap.h"
|
||||
#include "wolftpm/tpm2_tis.h" /* for TIS header size and wait state */
|
||||
static WOLFTPM2_DEV wolftpm_dev;
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||
static WOLFTPM2_SESSION wolftpm_session;
|
||||
static WOLFTPM2_KEY wolftpm_srk;
|
||||
#endif
|
||||
#endif /* WOLFBOOT_TPM */
|
||||
|
||||
#if defined(WOLFBOOT_TPM_KEYSTORE) && !defined(WOLFBOOT_TPM)
|
||||
#error For TPM keystore please make sure WOLFBOOT_TPM is also defined
|
||||
#include "tpm.h"
|
||||
#endif
|
||||
|
||||
/* Globals */
|
||||
static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
|
||||
/* Forward declarations */
|
||||
/**
|
||||
* @brief Find the key slot ID based on the SHA hash of the key.
|
||||
*
|
||||
* @param hint The SHA hash to find the key slot ID for.
|
||||
* @return The key slot ID corresponding to the provided SHA hash.
|
||||
*/
|
||||
static int keyslot_id_by_sha(const uint8_t *hint);
|
||||
|
||||
#ifdef WOLFBOOT_SIGN_ED25519
|
||||
#include <wolfssl/wolfcrypt/ed25519.h>
|
||||
|
@ -144,7 +123,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
|||
uint8_t *pubkey = keystore_get_buffer(key_slot);
|
||||
int pubkey_sz = keystore_get_size(key_slot);
|
||||
int point_sz = pubkey_sz/2;
|
||||
#ifdef WOLFBOOT_TPM
|
||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
||||
WOLFTPM2_KEY tpmKey;
|
||||
#else
|
||||
ecc_key ecc;
|
||||
|
@ -155,7 +134,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef WOLFBOOT_TPM
|
||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
||||
/* Use TPM for ECC verify */
|
||||
/* Load public key into TPM */
|
||||
memset(&tpmKey, 0, sizeof(tpmKey));
|
||||
|
@ -203,10 +182,10 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
|||
}
|
||||
wc_ecc_free(&ecc);
|
||||
}
|
||||
#endif /* WOLFBOOT_TPM */
|
||||
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY*/
|
||||
}
|
||||
|
||||
#endif /* WOLFBOOT_SIGN_ECC256 */
|
||||
#endif /* WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC521 */
|
||||
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_RSA2048) || \
|
||||
|
@ -268,7 +247,7 @@ static int RsaDecodeSignature(uint8_t** pInput, int inputSz)
|
|||
}
|
||||
#endif /* !NO_RSA_SIG_ENCODING */
|
||||
|
||||
#ifdef WOLFBOOT_TPM
|
||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
||||
/* RSA PKCSV15 un-padding with RSA_BLOCK_TYPE_1 (public) */
|
||||
/* UnPad plaintext, set start to *output, return length of plaintext or error */
|
||||
static int RsaUnPad(const byte *pkcsBlock, int pkcsBlockLen, byte **output)
|
||||
|
@ -291,7 +270,7 @@ static int RsaUnPad(const byte *pkcsBlock, int pkcsBlockLen, byte **output)
|
|||
ret = pkcsBlockLen - i;
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFBOOT_TPM */
|
||||
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY*/
|
||||
|
||||
static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||
struct wolfBoot_image *img, uint8_t *sig)
|
||||
|
@ -303,7 +282,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
|||
uint8_t *pubkey = keystore_get_buffer(key_slot);
|
||||
int pubkey_sz = keystore_get_size(key_slot);
|
||||
word32 inOutIdx = 0;
|
||||
#ifdef WOLFBOOT_TPM
|
||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
||||
WOLFTPM2_KEY tpmKey;
|
||||
const byte *n = NULL, *e = NULL;
|
||||
word32 nSz = 0, eSz = 0;
|
||||
|
@ -315,7 +294,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef WOLFBOOT_TPM
|
||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
||||
/* Extract DER RSA key struct */
|
||||
memset(&tpmKey, 0, sizeof(tpmKey));
|
||||
ret = wc_RsaPublicKeyDecode_ex(pubkey, &inOutIdx, pubkey_sz,
|
||||
|
@ -378,7 +357,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
|||
}
|
||||
#endif /* SCE || TSIP */
|
||||
wc_FreeRsaKey(&rsa);
|
||||
#endif /* WOLFBOOT_TPM */
|
||||
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY*/
|
||||
|
||||
#ifndef NO_RSA_SIG_ENCODING
|
||||
if (ret > WOLFBOOT_SHA_DIGEST_SIZE) {
|
||||
|
@ -480,7 +459,8 @@ static uint16_t get_header_ext(struct wolfBoot_image *img, uint16_t type,
|
|||
* @param ptr A pointer to store the position of the header.
|
||||
* @return The size of the data if found, otherwise 0.
|
||||
*/
|
||||
static uint16_t get_header(struct wolfBoot_image *img, uint16_t type,
|
||||
#define get_header wolfBoot_get_header /* internal reference to function */
|
||||
uint16_t wolfBoot_get_header(struct wolfBoot_image *img, uint16_t type,
|
||||
uint8_t **ptr)
|
||||
{
|
||||
if (PART_IS_EXT(img))
|
||||
|
@ -560,36 +540,6 @@ static uint8_t *get_img_hdr(struct wolfBoot_image *img)
|
|||
#if defined(WOLFBOOT_HASH_SHA256)
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
|
||||
#ifdef WOLFBOOT_MEASURED_BOOT
|
||||
static int self_sha256(uint8_t *hash)
|
||||
{
|
||||
uintptr_t p = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
|
||||
uint32_t sz = (uint32_t)WOLFBOOT_PARTITION_SIZE;
|
||||
uint32_t blksz, position = 0;
|
||||
wc_Sha256 sha256_ctx;
|
||||
|
||||
wc_InitSha256(&sha256_ctx);
|
||||
do {
|
||||
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
|
||||
if (position + blksz > sz)
|
||||
blksz = sz - position;
|
||||
#if defined(EXT_FLASH) && defined(NO_XIP)
|
||||
rc = ext_flash_read(p, ext_hash_block, WOLFBOOT_SHA_BLOCK_SIZE);
|
||||
if (rc != WOLFBOOT_SHA_BLOCK_SIZE)
|
||||
return -1;
|
||||
wc_Sha256Update(&sha256_ctx, ext_hash_block, blksz);
|
||||
#else
|
||||
wc_Sha256Update(&sha256_ctx, (uint8_t*)p, blksz);
|
||||
#endif
|
||||
position += blksz;
|
||||
p += blksz;
|
||||
} while (position < sz);
|
||||
wc_Sha256Final(&sha256_ctx, hash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLFBOOT_MEASURED_BOOT */
|
||||
|
||||
/**
|
||||
* @brief Calculate the SHA256 hash of the image.
|
||||
*
|
||||
|
@ -672,36 +622,6 @@ static void key_sha256(uint8_t key_slot, uint8_t *hash)
|
|||
#if defined(WOLFBOOT_HASH_SHA384)
|
||||
#include <wolfssl/wolfcrypt/sha512.h>
|
||||
|
||||
#ifdef WOLFBOOT_MEASURED_BOOT
|
||||
static int self_sha384(uint8_t *hash)
|
||||
{
|
||||
uintptr_t p = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
|
||||
uint32_t sz = (uint32_t)WOLFBOOT_PARTITION_SIZE;
|
||||
uint32_t blksz, position = 0;
|
||||
wc_Sha384 sha384_ctx;
|
||||
|
||||
wc_InitSha384(&sha384_ctx);
|
||||
do {
|
||||
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
|
||||
if (position + blksz > sz)
|
||||
blksz = sz - position;
|
||||
#if defined(EXT_FLASH) && defined(NO_XIP)
|
||||
rc = ext_flash_read(p, ext_hash_block, WOLFBOOT_SHA_BLOCK_SIZE);
|
||||
if (rc != WOLFBOOT_SHA_BLOCK_SIZE)
|
||||
return -1;
|
||||
wc_Sha384Update(&sha384_ctx, ext_hash_block, blksz);
|
||||
#else
|
||||
wc_Sha384Update(&sha384_ctx, (uint8_t*)p, blksz);
|
||||
#endif
|
||||
position += blksz;
|
||||
p += blksz;
|
||||
} while (position < sz);
|
||||
wc_Sha384Final(&sha384_ctx, hash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLFBOOT_MEASURED_BOOT */
|
||||
|
||||
/**
|
||||
* @brief Calculate SHA-384 hash of the image.
|
||||
*
|
||||
|
@ -876,340 +796,6 @@ static void key_sha3_384(uint8_t key_slot, uint8_t *hash)
|
|||
#endif /* WOLFBOOT_NO_SIGN */
|
||||
#endif /* SHA3-384 */
|
||||
|
||||
#ifdef WOLFBOOT_TPM
|
||||
#if defined(DEBUG_WOLFTPM) || defined(WOLFTPM_DEBUG_IO) || \
|
||||
defined(WOLFBOOT_DEBUG_TPM)
|
||||
#define LINE_LEN 16
|
||||
static void wolfBoot_PrintBin(const byte* buffer, word32 length)
|
||||
{
|
||||
word32 i, sz;
|
||||
|
||||
if (!buffer) {
|
||||
wolfBoot_printf("\tNULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (length > 0) {
|
||||
sz = length;
|
||||
if (sz > LINE_LEN)
|
||||
sz = LINE_LEN;
|
||||
|
||||
wolfBoot_printf("\t");
|
||||
for (i = 0; i < LINE_LEN; i++) {
|
||||
if (i < length)
|
||||
wolfBoot_printf("%02x ", buffer[i]);
|
||||
else
|
||||
wolfBoot_printf(" ");
|
||||
}
|
||||
wolfBoot_printf("| ");
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (buffer[i] > 31 && buffer[i] < 127)
|
||||
wolfBoot_printf("%c", buffer[i]);
|
||||
else
|
||||
wolfBoot_printf(".");
|
||||
}
|
||||
wolfBoot_printf("\r\n");
|
||||
|
||||
buffer += sz;
|
||||
length -= sz;
|
||||
}
|
||||
}
|
||||
#endif /* WOLFTPM_DEBUG_IO || WOLFBOOT_DEBUG_TPM */
|
||||
|
||||
#if !defined(ARCH_SIM) && !defined(WOLFTPM_MMIO)
|
||||
#ifdef WOLFTPM_ADV_IO
|
||||
static int TPM2_IoCb(TPM2_CTX* ctx, int isRead, word32 addr, byte* buf,
|
||||
word16 size, void* userCtx)
|
||||
#else
|
||||
|
||||
/**
|
||||
* @brief TPM2 I/O callback function for communication with TPM2 device.
|
||||
*
|
||||
* This function is used as the I/O callback function for communication
|
||||
* with the TPM2 device. It is called during TPM operations to send and
|
||||
* receive data from the TPM2 device.
|
||||
*
|
||||
* @param ctx The pointer to the TPM2 context.
|
||||
* @param txBuf The buffer containing data to be sent to the TPM2 device.
|
||||
* @param rxBuf The buffer to store the received data from the TPM2 device.
|
||||
* @param xferSz The size of the data to be transferred.
|
||||
* @param userCtx The user context (not used in this implementation).
|
||||
* @return The return code from the TPM2 device operation.
|
||||
*/
|
||||
static int TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
|
||||
word16 xferSz, void* userCtx)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
#ifdef WOLFTPM_CHECK_WAIT_STATE
|
||||
int timeout = TPM_SPI_WAIT_RETRY;
|
||||
#endif
|
||||
#ifdef WOLFTPM_ADV_IO
|
||||
byte txBuf[MAX_SPI_FRAMESIZE+TPM_TIS_HEADER_SZ];
|
||||
byte rxBuf[MAX_SPI_FRAMESIZE+TPM_TIS_HEADER_SZ];
|
||||
int xferSz = TPM_TIS_HEADER_SZ + size;
|
||||
|
||||
#ifdef WOLFTPM_DEBUG_IO
|
||||
wolfBoot_printf("TPM2_IoCb (Adv): Read %d, Addr %x, Size %d\n",
|
||||
isRead ? 1 : 0, addr, size);
|
||||
if (!isRead) {
|
||||
wolfBoot_PrintBin(buf, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Build TPM header */
|
||||
txBuf[1] = (addr>>16) & 0xFF;
|
||||
txBuf[2] = (addr>>8) & 0xFF;
|
||||
txBuf[3] = (addr) & 0xFF;
|
||||
if (isRead) {
|
||||
txBuf[0] = TPM_TIS_READ | ((size & 0xFF) - 1);
|
||||
memset(&txBuf[TPM_TIS_HEADER_SZ], 0, size);
|
||||
}
|
||||
else {
|
||||
txBuf[0] = TPM_TIS_WRITE | ((size & 0xFF) - 1);
|
||||
memcpy(&txBuf[TPM_TIS_HEADER_SZ], buf, size);
|
||||
}
|
||||
memset(rxBuf, 0, sizeof(rxBuf));
|
||||
#endif /* WOLFTPM_ADV_IO */
|
||||
|
||||
#ifdef WOLFTPM_CHECK_WAIT_STATE /* Handle TIS wait states */
|
||||
/* Send header - leave CS asserted */
|
||||
ret = spi_xfer(SPI_CS_TPM, txBuf, rxBuf, TPM_TIS_HEADER_SZ,
|
||||
0x1 /* 1=SPI_XFER_FLAG_CONTINUE */
|
||||
);
|
||||
|
||||
/* Handle wait states */
|
||||
while (ret == 0 &&
|
||||
--timeout > 0 &&
|
||||
(rxBuf[TPM_TIS_HEADER_SZ-1] & TPM_TIS_READY_MASK) == 0)
|
||||
{
|
||||
/* clock additional byte until 0x01 LSB is set (keep CS asserted) */
|
||||
ret = spi_xfer(SPI_CS_TPM,
|
||||
&txBuf[TPM_TIS_HEADER_SZ-1],
|
||||
&rxBuf[TPM_TIS_HEADER_SZ-1], 1,
|
||||
0x1 /* 1=SPI_XFER_FLAG_CONTINUE */
|
||||
);
|
||||
}
|
||||
/* Check for timeout */
|
||||
if (ret == 0 && timeout <= 0) {
|
||||
ret = TPM_RC_FAILURE;
|
||||
}
|
||||
|
||||
/* Transfer remainder of payload (command / response) */
|
||||
if (ret == 0) {
|
||||
ret = spi_xfer(SPI_CS_TPM,
|
||||
&txBuf[TPM_TIS_HEADER_SZ],
|
||||
&rxBuf[TPM_TIS_HEADER_SZ],
|
||||
xferSz-TPM_TIS_HEADER_SZ,
|
||||
0 /* de-assert CS*/ );
|
||||
}
|
||||
/* On error make sure SPI is de-asserted */
|
||||
else {
|
||||
spi_xfer(SPI_CS_TPM, NULL, NULL, 0, 0);
|
||||
return ret;
|
||||
}
|
||||
#else /* Send Entire Message - no wait states */
|
||||
ret = spi_xfer(SPI_CS_TPM, txBuf, rxBuf, xferSz, 0);
|
||||
|
||||
#ifdef WOLFTPM_DEBUG_IO
|
||||
wolfBoot_printf("TPM2_IoCb: Ret %d, Sz %d\n", ret, xferSz);
|
||||
wolfBoot_PrintBin(txBuf, xferSz);
|
||||
wolfBoot_PrintBin(rxBuf, xferSz);
|
||||
#endif
|
||||
#endif /* !WOLFTPM_CHECK_WAIT_STATE */
|
||||
|
||||
#ifdef WOLFTPM_ADV_IO
|
||||
if (isRead) {
|
||||
memcpy(buf, &rxBuf[TPM_TIS_HEADER_SZ], size);
|
||||
#ifdef WOLFTPM_DEBUG_IO
|
||||
wolfBoot_PrintBin(buf, size);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* !ARCH_SIM && !WOLFTPM_MMIO */
|
||||
|
||||
#ifdef WOLFBOOT_MEASURED_BOOT
|
||||
#define measure_boot(hash) wolfBoot_tpm2_extend((hash), __LINE__)
|
||||
/**
|
||||
* @brief Extends a PCR in the TPM with a hash.
|
||||
*
|
||||
* Extends a specified PCR's value in the TPM with a given hash. Uses
|
||||
* TPM2_PCR_Extend. Optionally, if DEBUG_WOLFTPM or WOLFBOOT_DEBUG_TPM defined,
|
||||
* prints debug info.
|
||||
*
|
||||
* @param[in] hash Pointer to the hash value to extend into the PCR.
|
||||
* @param[in] line Line number where the function is called (for debugging).
|
||||
* @return 0 on success, an error code on failure.
|
||||
*
|
||||
*/
|
||||
static int wolfBoot_tpm2_extend(uint8_t* hash, int line)
|
||||
{
|
||||
int rc;
|
||||
PCR_Extend_In pcrExtend;
|
||||
#ifdef WOLFBOOT_DEBUG_TPM
|
||||
PCR_Read_In pcrReadCmd;
|
||||
PCR_Read_Out pcrReadResp;
|
||||
#endif
|
||||
|
||||
pcrExtend.pcrHandle = WOLFBOOT_MEASURED_PCR_A;
|
||||
pcrExtend.digests.count = 1;
|
||||
pcrExtend.digests.digests[0].hashAlg = TPM_ALG_SHA256;
|
||||
XMEMCPY(pcrExtend.digests.digests[0].digest.H,
|
||||
hash, TPM_SHA256_DIGEST_SIZE);
|
||||
|
||||
rc = TPM2_PCR_Extend(&pcrExtend);
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
wolfBoot_printf("Measured boot: Res %d, Index %d, Line %d\n",
|
||||
rc, pcrExtend.pcrHandle, line);
|
||||
#endif
|
||||
|
||||
#ifdef WOLFBOOT_DEBUG_TPM
|
||||
if (rc == 0) {
|
||||
memset(&pcrReadCmd, 0, sizeof(pcrReadCmd));
|
||||
memset(&pcrReadResp, 0, sizeof(pcrReadResp));
|
||||
TPM2_SetupPCRSel(&pcrReadCmd.pcrSelectionIn, TPM_ALG_SHA256,
|
||||
pcrExtend.pcrHandle);
|
||||
rc = TPM2_PCR_Read(&pcrReadCmd, &pcrReadResp);
|
||||
|
||||
wolfBoot_printf("PCR %d: Res %d, Digest Sz %d, Update Counter %d\n",
|
||||
pcrExtend.pcrHandle, rc,
|
||||
(int)pcrReadResp.pcrValues.digests[0].size,
|
||||
(int)pcrReadResp.pcrUpdateCounter);
|
||||
wolfBoot_PrintBin(pcrReadResp.pcrValues.digests[0].buffer,
|
||||
pcrReadResp.pcrValues.digests[0].size);
|
||||
}
|
||||
#endif
|
||||
(void)line;
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif /* WOLFBOOT_MEASURED_BOOT */
|
||||
|
||||
#if defined(WOLFBOOT_TPM_KEYSTORE) && defined(WC_RNG_SEED_CB)
|
||||
static int wolfRNG_GetSeedCB(OS_Seed* os, byte* seed, word32 sz)
|
||||
{
|
||||
(void)os;
|
||||
return wolfTPM2_GetRandom(&wolftpm_dev, seed, sz);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the TPM2 device and retrieve its capabilities.
|
||||
*
|
||||
* This function initializes the TPM2 device and retrieves its capabilities.
|
||||
*
|
||||
* @return 0 on success, an error code on failure.
|
||||
*/
|
||||
int wolfBoot_tpm2_init(void)
|
||||
{
|
||||
int rc;
|
||||
word32 idx;
|
||||
WOLFTPM2_CAPS caps;
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||
TPM_ALG_ID alg;
|
||||
#endif
|
||||
|
||||
#if !defined(ARCH_SIM) && !defined(WOLFTPM_MMIO)
|
||||
spi_init(0,0);
|
||||
#endif
|
||||
|
||||
/* Init the TPM2 device */
|
||||
/* simulator should use the network connection, not spi */
|
||||
#if defined(ARCH_SIM) || defined(WOLFTPM_MMIO)
|
||||
rc = wolfTPM2_Init(&wolftpm_dev, NULL, NULL);
|
||||
#else
|
||||
rc = wolfTPM2_Init(&wolftpm_dev, TPM2_IoCb, NULL);
|
||||
#endif
|
||||
if (rc == 0) {
|
||||
/* Get device capabilities + options */
|
||||
rc = wolfTPM2_GetCapabilities(&wolftpm_dev, &caps);
|
||||
}
|
||||
if (rc == 0) {
|
||||
wolfBoot_printf("Mfg %s (%d), Vendor %s, Fw %u.%u (0x%x), "
|
||||
"FIPS 140-2 %d, CC-EAL4 %d\n",
|
||||
caps.mfgStr, caps.mfg, caps.vendorStr, caps.fwVerMajor,
|
||||
caps.fwVerMinor, caps.fwVerVendor, caps.fips140_2, caps.cc_eal4);
|
||||
}
|
||||
else {
|
||||
wolfBoot_printf("TPM Init failed! %d\n", rc);
|
||||
}
|
||||
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||
memset(&wolftpm_session, 0, sizeof(wolftpm_session));
|
||||
|
||||
#ifdef WC_RNG_SEED_CB
|
||||
/* setup callback for RNG seed to use TPM */
|
||||
wc_SetSeed_Cb(wolfRNG_GetSeedCB);
|
||||
#endif
|
||||
|
||||
/* Create a primary storage key - no auth (used for parameter encryption) */
|
||||
#ifdef HAVE_ECC
|
||||
alg = TPM_ALG_ECC;
|
||||
#elif !defined(NO_RSA)
|
||||
alg = TPM_ALG_RSA;
|
||||
#else
|
||||
alg = TPM_ALG_NULL;
|
||||
#endif
|
||||
rc = wolfTPM2_CreateSRK(&wolftpm_dev, &wolftpm_srk, alg, NULL, 0);
|
||||
if (rc == 0) {
|
||||
/* Setup a TPM session that can be used for parameter encryption */
|
||||
rc = wolfTPM2_StartSession(&wolftpm_dev, &wolftpm_session, &wolftpm_srk,
|
||||
NULL, TPM_SE_HMAC, TPM_ALG_CFB);
|
||||
}
|
||||
if (rc != 0) {
|
||||
wolfBoot_printf("TPM Create SRK or Start Session error %d (%s)!\n",
|
||||
rc, wolfTPM2_GetRCString(rc));
|
||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &wolftpm_session.handle);
|
||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &wolftpm_srk.handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFBOOT_MEASURED_BOOT
|
||||
/* hash wolfBoot and extend PCR */
|
||||
rc = self_hash(digest);
|
||||
if (rc == 0) {
|
||||
rc = measure_boot(digest);
|
||||
}
|
||||
if (rc != 0) {
|
||||
wolfBoot_printf("Error %d performing wolfBoot measurement!\n", rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the TPM2 device.
|
||||
*
|
||||
* This function deinitializes the TPM2 device and cleans up any resources.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void wolfBoot_tpm2_deinit(void)
|
||||
{
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||
#if !defined(ARCH_SIM) && !defined(WOLFBOOT_TPM_NO_CHG_PLAT_AUTH)
|
||||
/* Change platform auth to random value, to prevent application from being
|
||||
* able to use platform hierarchy. This is defined in section 10 of the
|
||||
* TCG PC Client Platform specification.
|
||||
*/
|
||||
int rc = wolfTPM2_ChangePlatformAuth(&wolftpm_dev, &wolftpm_session);
|
||||
if (rc != 0) {
|
||||
wolfBoot_printf("Error %d setting platform auth\n", rc);
|
||||
}
|
||||
#endif
|
||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &wolftpm_session.handle);
|
||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &wolftpm_srk.handle);
|
||||
#endif /* WOLFBOOT_TPM_KEYSTORE */
|
||||
|
||||
wolfTPM2_Cleanup(&wolftpm_dev);
|
||||
}
|
||||
|
||||
#endif /* WOLFBOOT_TPM */
|
||||
|
||||
/**
|
||||
* @brief Convert a 32-bit integer from little-endian to native byte order.
|
||||
*
|
||||
|
@ -1482,8 +1068,15 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
|
|||
if (key_slot < 0) {
|
||||
return -1; /* Key was not found */
|
||||
}
|
||||
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||
if (wolfBoot_check_rot(key_slot, pubkey_hint) != 0) {
|
||||
return -1; /* TPM root of trust failed! */
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1; /* Invalid hash size for public key hint */
|
||||
}
|
||||
image_type_size = get_header(img, HDR_IMG_TYPE, &image_type_buf);
|
||||
|
@ -1501,8 +1094,9 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
|
|||
image_part = image_type & HDR_IMG_TYPE_PART_MASK;
|
||||
|
||||
/* Check if the key permission mask matches the current partition id */
|
||||
if (((1U << image_part) & key_mask) != (1U << image_part))
|
||||
if (((1U << image_part) & key_mask) != (1U << image_part)) {
|
||||
return -1; /* Key not allowed to verify this partition id */
|
||||
}
|
||||
|
||||
CONFIRM_MASK_VALID(image_part, key_mask);
|
||||
|
||||
|
@ -1552,51 +1146,22 @@ uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
|
|||
* @param hint The SHA hash of the public key to search for.
|
||||
* @return The key slot ID if found, -1 if the key was not found.
|
||||
*/
|
||||
static int keyslot_id_by_sha(const uint8_t *hint)
|
||||
int keyslot_id_by_sha(const uint8_t *hint)
|
||||
{
|
||||
int id;
|
||||
#ifdef STAGE1_AUTH
|
||||
/* Override global */
|
||||
uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
#endif
|
||||
|
||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_KEYSTORE)
|
||||
/* use public key hash (hint) */
|
||||
int rc;
|
||||
WOLFTPM2_NV nv;
|
||||
word32 digestSz = (word32)TPM2_GetHashDigestSize(WOLFBOOT_TPM_HASH_ALG);
|
||||
XMEMSET(&nv, 0, sizeof(nv));
|
||||
nv.handle.hndl = WOLFBOOT_TPM_KEYSTORE_NV_INDEX;
|
||||
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE_AUTH
|
||||
nv.handle.auth.size = (UINT16)strlen(WOLFBOOT_TPM_KEYSTORE_AUTH);
|
||||
memcpy(nv.handle.auth.buffer, WOLFBOOT_TPM_KEYSTORE_AUTH, nv.handle.auth.size);
|
||||
#endif
|
||||
|
||||
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, WOLFBOOT_TPM_KEYSTORE_NV_INDEX,
|
||||
digest, &digestSz, 0);
|
||||
if (rc == 0 && memcmp(digest, hint, WOLFBOOT_SHA_DIGEST_SIZE) == 0) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
wolfBoot_printf("TPM Root of Trust valid\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
wolfBoot_printf("TPM Root of Trust failed! %d (%s)\n",
|
||||
rc, wolfTPM2_GetRCString(rc));
|
||||
wolfBoot_printf("Expected Hash %d\n", WOLFBOOT_SHA_DIGEST_SIZE);
|
||||
wolfBoot_PrintBin(hint, WOLFBOOT_SHA_DIGEST_SIZE);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
int id = 0;
|
||||
for (id = 0; id < keystore_num_pubkeys(); id++) {
|
||||
key_hash(id, digest);
|
||||
if (memcmp(digest, hint, WOLFBOOT_SHA_DIGEST_SIZE) == 0)
|
||||
if (memcmp(digest, hint, WOLFBOOT_SHA_DIGEST_SIZE) == 0) {
|
||||
return id;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif /* !WOLFBOOT_NO_SIGN && !WOLFBOOT_RENESAS_SCEPROTECT */
|
||||
|
||||
#endif /* IMAGE_H_ */
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#include "uart_flash.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
#ifdef WOLFBOOT_TPM
|
||||
#include "tpm.h"
|
||||
#endif
|
||||
|
||||
#ifdef RAM_CODE
|
||||
/**
|
||||
* @brief Start address of the text section in RAM code.
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "wolfboot/wolfboot.h"
|
||||
#include "delta.h"
|
||||
#include "printf.h"
|
||||
|
||||
#include "tpm.h"
|
||||
|
||||
#ifdef RAM_CODE
|
||||
extern unsigned int _start_text;
|
||||
|
@ -568,11 +568,89 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(ARCH_SIM) && defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_SEAL)
|
||||
int wolfBoot_unlock_disk(void)
|
||||
{
|
||||
int ret;
|
||||
struct wolfBoot_image img;
|
||||
WOLFTPM2_KEYBLOB seal_blob;
|
||||
uint8_t secret[WOLFBOOT_MAX_SEAL_SZ];
|
||||
int secretSz;
|
||||
uint8_t* policy = NULL;
|
||||
uint16_t policySz = 0;
|
||||
|
||||
memset(&seal_blob, 0, sizeof(seal_blob));
|
||||
memset(secret, 0, sizeof(secret));
|
||||
|
||||
wolfBoot_printf("Unlocking disk...\n");
|
||||
|
||||
/* check policy */
|
||||
ret = wolfBoot_open_image(&img, PART_BOOT);
|
||||
if (ret == 0) {
|
||||
ret = wolfBoot_get_policy(&img, &policy, &policySz);
|
||||
if (ret == -TPM_RC_POLICY_FAIL) {
|
||||
/* the image is not signed with a policy */
|
||||
wolfBoot_printf("Image policy signature missing!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* for testing seal and unseal */
|
||||
/* create secret to seal */
|
||||
secretSz = 32;
|
||||
ret = wolfBoot_get_random(secret, secretSz);
|
||||
if (ret == 0) {
|
||||
wolfBoot_printf("Sealing %d bytes\n", secretSz);
|
||||
wolfBoot_print_hexstr(secret, secretSz, 0);
|
||||
|
||||
/* seal new secret */
|
||||
ret = wolfBoot_seal_blob(&img, &seal_blob, secret, secretSz);
|
||||
}
|
||||
if (ret == 0) {
|
||||
uint8_t secretCheck[WOLFBOOT_MAX_SEAL_SZ];
|
||||
int secretCheckSz = 0;
|
||||
|
||||
/* unseal again to make sure it works */
|
||||
memset(secretCheck, 0, sizeof(secretCheck));
|
||||
ret = wolfBoot_unseal_blob(&img, &seal_blob, secretCheck, &secretCheckSz);
|
||||
if (ret == 0) {
|
||||
if (secretSz != secretCheckSz || memcmp(secret, secretCheck, secretSz) != 0) {
|
||||
wolfBoot_printf("secret check mismatch!\n");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
wolfBoot_printf("Unsealed %d bytes\n", secretCheckSz);
|
||||
wolfBoot_print_hexstr(secretCheck, secretCheckSz, 0);
|
||||
TPM2_ForceZero(secretCheck, sizeof(secretCheck));
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* TODO: Unlock disk */
|
||||
|
||||
}
|
||||
else {
|
||||
wolfBoot_printf("unlock disk failed! %d (%s)\n",
|
||||
ret, wolfTPM2_GetRCString(ret));
|
||||
}
|
||||
TPM2_ForceZero(secret, sizeof(secretSz));
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void RAMFUNCTION wolfBoot_start(void)
|
||||
{
|
||||
uint8_t st;
|
||||
struct wolfBoot_image boot;
|
||||
|
||||
#if defined(ARCH_SIM) && defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_SEAL)
|
||||
wolfBoot_unlock_disk();
|
||||
#endif
|
||||
|
||||
#ifdef RAM_CODE
|
||||
wolfBoot_check_self_update();
|
||||
#endif
|
||||
|
|
|
@ -44,23 +44,21 @@ void hal_init(void);
|
|||
|
||||
int do_cmd(const char *cmd)
|
||||
{
|
||||
if (strcmp(cmd, "powerfail") == 0)
|
||||
if (strcmp(cmd, "powerfail") == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(cmd, "get_version") == 0) {
|
||||
printf("%d\n", wolfBoot_current_firmware_version());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "success") == 0) {
|
||||
wolfBoot_success();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "update_trigger") == 0) {
|
||||
wolfBoot_update_trigger();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "reset") == 0) {
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,10 @@ ifeq ($(ARCH),)
|
|||
PKA?=1
|
||||
PSOC6_CRYPTO?=1
|
||||
WOLFTPM?=0
|
||||
WOLFBOOT_TPM_VERIFY?=0
|
||||
MEASURED_BOOT?=0
|
||||
WOLFBOOT_TPM_SEAL?=0
|
||||
WOLFBOOT_TPM_KEYSTORE?=0
|
||||
TZEN?=0
|
||||
WOLFBOOT_PARTITION_SIZE?=0x20000
|
||||
WOLFBOOT_SECTOR_SIZE?=0x20000
|
||||
|
@ -73,7 +77,8 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO
|
|||
MCUXPRESSO_CMSIS FREEDOM_E_SDK STM32CUBE CYPRESS_PDL CYPRESS_CORE_LIB CYPRESS_TARGET_LIB DEBUG VTOR \
|
||||
CORTEX_M0 CORTEX_M7 CORTEX_M33 NO_ASM EXT_FLASH SPI_FLASH NO_XIP UART_FLASH ALLOW_DOWNGRADE NVM_FLASH_WRITEONCE \
|
||||
DISABLE_BACKUP WOLFBOOT_VERSION V NO_MPU ENCRYPT FLAGS_HOME FLAGS_INVERT \
|
||||
SPMATH SPMATHALL RAM_CODE DUALBANK_SWAP IMAGE_HEADER_SIZE PKA TZEN PSOC6_CRYPTO WOLFTPM \
|
||||
SPMATH SPMATHALL RAM_CODE DUALBANK_SWAP IMAGE_HEADER_SIZE PKA TZEN PSOC6_CRYPTO \
|
||||
WOLFTPM WOLFBOOT_TPM_VERIFY MEASURED_BOOT WOLFBOOT_TPM_SEAL WOLFBOOT_TPM_KEYSTORE \
|
||||
WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE \
|
||||
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
|
||||
WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \
|
||||
|
@ -83,4 +88,3 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO
|
|||
ENCRYPT_WITH_CHACHA ENCRYPT_WITH_AES128 ENCRYPT_WITH_AES256 ARMORED \
|
||||
LMS_LEVELS LMS_HEIGHT LMS_WINTERNITZ \
|
||||
ELF
|
||||
|
||||
|
|
|
@ -26,11 +26,13 @@ ifeq ($(SIGN),LMS)
|
|||
endif
|
||||
|
||||
# option variables
|
||||
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE -fsanitize=address
|
||||
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE
|
||||
SANITIZE_FLAGS = -fsanitize=address
|
||||
OPTIMIZE = -O2
|
||||
|
||||
# Options
|
||||
#CFLAGS+=$(DEBUG_FLAGS)
|
||||
#CFLAGS+=$(SANITIZE_FLAGS)
|
||||
CFLAGS+=$(OPTIMIZE)
|
||||
|
||||
ifeq ($(IMAGE_HEADER_SIZE),)
|
||||
|
|
|
@ -101,7 +101,7 @@ static inline int fp_truncate(FILE *f, size_t len)
|
|||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#ifdef WOLFSSL_HAVE_LMS
|
||||
#include <wolfssl/wolfcrypt/lms.h>
|
||||
#ifdef HAVE_LIBLMS
|
||||
#include <wolfssl/wolfcrypt/ext_lms.h>
|
||||
|
@ -199,7 +199,7 @@ static void header_append_tag(uint8_t* header, uint32_t* idx, uint16_t tag,
|
|||
*idx += len;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#ifdef WOLFSSL_HAVE_LMS
|
||||
#include "../lms/lms_common.h"
|
||||
#endif
|
||||
|
||||
|
@ -219,7 +219,7 @@ static union {
|
|||
#ifndef NO_RSA
|
||||
RsaKey rsa;
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#ifdef WOLFSSL_HAVE_LMS
|
||||
LmsKey lms;
|
||||
#endif
|
||||
} key;
|
||||
|
@ -238,7 +238,7 @@ struct cmd_options {
|
|||
const char *key_file;
|
||||
const char *fw_version;
|
||||
const char *signature_file;
|
||||
const char* policy_signature_file;
|
||||
const char *policy_file;
|
||||
const char *encrypt_key_file;
|
||||
const char *delta_base_file;
|
||||
char output_image_file[PATH_MAX];
|
||||
|
@ -247,6 +247,7 @@ struct cmd_options {
|
|||
uint32_t pubkey_sz;
|
||||
uint32_t header_sz;
|
||||
uint32_t signature_sz;
|
||||
uint32_t policy_sz;
|
||||
uint8_t partition_id;
|
||||
};
|
||||
|
||||
|
@ -691,7 +692,7 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz,
|
|||
break;
|
||||
}
|
||||
}
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#ifdef WOLFSSL_HAVE_LMS
|
||||
FALL_THROUGH;
|
||||
case SIGN_LMS:
|
||||
ret = -1;
|
||||
|
@ -728,7 +729,7 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz,
|
|||
*key_buffer_sz );
|
||||
}
|
||||
}
|
||||
#endif /* defined(WOLFSSL_HAVE_LMS) */
|
||||
#endif /* WOLFSSL_HAVE_LMS */
|
||||
break;
|
||||
} /* end switch (CMD.sign) */
|
||||
|
||||
|
@ -759,6 +760,115 @@ failure:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Sign the digest */
|
||||
static int sign_digest(int sign, int hash_algo,
|
||||
uint8_t* signature, uint32_t* signature_sz,
|
||||
uint8_t* digest, uint32_t digest_sz)
|
||||
{
|
||||
int ret;
|
||||
WC_RNG rng;
|
||||
|
||||
if ((ret = wc_InitRng(&rng)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ED25519
|
||||
if (sign == SIGN_ED25519) {
|
||||
ret = wc_ed25519_sign_msg(digest, digest_sz, signature,
|
||||
signature_sz, &key.ed);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_ED448
|
||||
if (sign == SIGN_ED448) {
|
||||
ret = wc_ed448_sign_msg(digest, digest_sz, signature,
|
||||
signature_sz, &key.ed4, NULL, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_ECC
|
||||
if (sign == SIGN_ECC256 ||
|
||||
sign == SIGN_ECC384 ||
|
||||
sign == SIGN_ECC521)
|
||||
{
|
||||
mp_int r, s;
|
||||
int sigSz;
|
||||
if (sign == SIGN_ECC256) sigSz = 32;
|
||||
if (sign == SIGN_ECC384) sigSz = 48;
|
||||
if (sign == SIGN_ECC521) sigSz = 66;
|
||||
|
||||
mp_init(&r); mp_init(&s);
|
||||
ret = wc_ecc_sign_hash_ex(digest, digest_sz, &rng, &key.ecc,
|
||||
&r, &s);
|
||||
mp_to_unsigned_bin(&r, &signature[0]);
|
||||
mp_to_unsigned_bin(&s, &signature[sigSz]);
|
||||
mp_clear(&r); mp_clear(&s);
|
||||
*signature_sz = sigSz*2;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef NO_RSA
|
||||
if (sign == SIGN_RSA2048 ||
|
||||
sign == SIGN_RSA3072 ||
|
||||
sign == SIGN_RSA4096)
|
||||
{
|
||||
#ifndef WC_MAX_ENCODED_DIG_ASN_SZ
|
||||
#define WC_MAX_ENCODED_DIG_ASN_SZ 9 /* enum(bit or octet) + length(4) */
|
||||
#endif
|
||||
uint8_t buf[WC_MAX_DIGEST_SIZE + WC_MAX_ENCODED_DIG_ASN_SZ];
|
||||
uint32_t enchash_sz = digest_sz;
|
||||
uint8_t* enchash = digest;
|
||||
if (CMD.sign_wenc) {
|
||||
/* add ASN.1 signature encoding */
|
||||
int hashOID = 0;
|
||||
if (hash_algo == HASH_SHA256)
|
||||
hashOID = SHA256h;
|
||||
else if (hash_algo == HASH_SHA384)
|
||||
hashOID = SHA384h;
|
||||
else if (hash_algo == HASH_SHA3)
|
||||
hashOID = SHA3_384h;
|
||||
enchash_sz = wc_EncodeSignature(buf, digest, digest_sz, hashOID);
|
||||
enchash = buf;
|
||||
}
|
||||
ret = wc_RsaSSL_Sign(enchash, enchash_sz, signature, *signature_sz,
|
||||
&key.rsa, &rng);
|
||||
if (ret > 0) {
|
||||
*signature_sz = ret;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef WOLFSSL_HAVE_LMS
|
||||
if (sign == SIGN_LMS) {
|
||||
/* Set the callbacks, so LMS can update the private key while signing */
|
||||
ret = wc_LmsKey_SetWriteCb(&key.lms, lms_write_key);
|
||||
if (ret == 0) {
|
||||
ret = wc_LmsKey_SetReadCb(&key.lms, lms_read_key);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_LmsKey_SetContext(&key.lms, (void*)CMD.key_file);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_LmsKey_Reload(&key.lms);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_LmsKey_Sign(&key.lms, signature, signature_sz, digest,
|
||||
digest_sz);
|
||||
}
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error signing with LMS: %d\n", ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* WOLFSSL_HAVE_LMS */
|
||||
{
|
||||
ret = NOT_COMPILED_IN;
|
||||
}
|
||||
wc_FreeRng(&rng);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
||||
const char *image_file, const char *outfile,
|
||||
uint32_t delta_base_version, uint32_t patch_len, uint32_t patch_inv_off,
|
||||
|
@ -771,7 +881,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
struct stat attrib;
|
||||
uint16_t image_type;
|
||||
uint8_t* signature = NULL;
|
||||
uint8_t* policy_signature = NULL;
|
||||
uint8_t* policy = NULL;
|
||||
int ret = -1;
|
||||
uint8_t buf[1024];
|
||||
uint32_t read_sz, pos;
|
||||
|
@ -999,7 +1109,6 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
/* Add image hash to header */
|
||||
header_append_tag(header, &header_idx, CMD.hash_algo, digest_sz, digest);
|
||||
if (CMD.sign != NO_SIGN) {
|
||||
WC_RNG rng;
|
||||
/* Add Pubkey Hash to header */
|
||||
header_append_tag(header, &header_idx, HDR_PUBKEY, digest_sz, buf);
|
||||
|
||||
|
@ -1015,137 +1124,27 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
printf("Digest image %s successfully created.\n", outfile);
|
||||
exit(0);
|
||||
}
|
||||
/* save max sig size */
|
||||
CMD.policy_sz = CMD.signature_sz;
|
||||
|
||||
/* Sign the digest */
|
||||
ret = NOT_COMPILED_IN; /* default error */
|
||||
/* Signing Image */
|
||||
signature = malloc(CMD.signature_sz);
|
||||
if (signature == NULL) {
|
||||
printf("Signature malloc error!\n");
|
||||
goto failure;
|
||||
}
|
||||
memset(signature, 0, CMD.signature_sz);
|
||||
if (CMD.manual_sign && CMD.policy_sign) {
|
||||
policy_signature = malloc(CMD.signature_sz);
|
||||
if (policy_signature == NULL) {
|
||||
printf("Policy Signature malloc error!\n");
|
||||
goto failure;
|
||||
}
|
||||
memset(policy_signature, 0, CMD.signature_sz);
|
||||
}
|
||||
|
||||
if (!CMD.manual_sign) {
|
||||
printf("Signing the digest...\n");
|
||||
#ifdef DEBUG_SIGTOOL
|
||||
#ifdef DEBUG_SIGNTOOL
|
||||
printf("Digest %d\n", digest_sz);
|
||||
WOLFSSL_BUFFER(digest, digest_sz);
|
||||
#endif
|
||||
wc_InitRng(&rng);
|
||||
if (CMD.sign == SIGN_ED25519) {
|
||||
#ifdef HAVE_ED25519
|
||||
ret = wc_ed25519_sign_msg(digest, digest_sz, signature,
|
||||
&CMD.signature_sz, &key.ed);
|
||||
#endif
|
||||
}
|
||||
else if (CMD.sign == SIGN_ED448) {
|
||||
#ifdef HAVE_ED448
|
||||
ret = wc_ed448_sign_msg(digest, digest_sz, signature,
|
||||
&CMD.signature_sz, &key.ed4, NULL, 0);
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_ECC
|
||||
else if (CMD.sign == SIGN_ECC256) {
|
||||
mp_int r, s;
|
||||
mp_init(&r); mp_init(&s);
|
||||
ret = wc_ecc_sign_hash_ex(digest, digest_sz, &rng, &key.ecc,
|
||||
&r, &s);
|
||||
mp_to_unsigned_bin(&r, &signature[0]);
|
||||
mp_to_unsigned_bin(&s, &signature[32]);
|
||||
mp_clear(&r); mp_clear(&s);
|
||||
}
|
||||
else if (CMD.sign == SIGN_ECC384) {
|
||||
mp_int r, s;
|
||||
mp_init(&r); mp_init(&s);
|
||||
ret = wc_ecc_sign_hash_ex(digest, digest_sz, &rng, &key.ecc,
|
||||
&r, &s);
|
||||
mp_to_unsigned_bin(&r, &signature[0]);
|
||||
mp_to_unsigned_bin(&s, &signature[48]);
|
||||
mp_clear(&r); mp_clear(&s);
|
||||
}
|
||||
else if (CMD.sign == SIGN_ECC521) {
|
||||
mp_int r, s;
|
||||
mp_init(&r); mp_init(&s);
|
||||
ret = wc_ecc_sign_hash_ex(digest, digest_sz, &rng, &key.ecc,
|
||||
&r, &s);
|
||||
mp_to_unsigned_bin(&r, &signature[0]);
|
||||
mp_to_unsigned_bin(&s, &signature[66]);
|
||||
mp_clear(&r); mp_clear(&s);
|
||||
}
|
||||
#endif
|
||||
else if (CMD.sign == SIGN_RSA2048 ||
|
||||
CMD.sign == SIGN_RSA3072 ||
|
||||
CMD.sign == SIGN_RSA4096) {
|
||||
|
||||
#ifndef NO_RSA
|
||||
uint32_t enchash_sz = digest_sz;
|
||||
uint8_t* enchash = digest;
|
||||
if (CMD.sign_wenc) {
|
||||
/* add ASN.1 signature encoding */
|
||||
int hashOID = 0;
|
||||
if (CMD.hash_algo == HASH_SHA256)
|
||||
hashOID = SHA256h;
|
||||
else if (CMD.hash_algo == HASH_SHA3)
|
||||
hashOID = SHA3_384h;
|
||||
enchash_sz = wc_EncodeSignature(buf, digest, digest_sz,
|
||||
hashOID);
|
||||
enchash = buf;
|
||||
}
|
||||
ret = wc_RsaSSL_Sign(enchash, enchash_sz, signature,
|
||||
CMD.signature_sz,
|
||||
&key.rsa, &rng);
|
||||
if (ret > 0) {
|
||||
CMD.signature_sz = ret;
|
||||
ret = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (CMD.sign == SIGN_LMS) {
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
/* Set the callbacks, so LMS can update the private key
|
||||
* while signing. */
|
||||
ret = wc_LmsKey_SetWriteCb(&key.lms, lms_write_key);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_LmsKey_SetWriteCb returned %d\n", ret);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
ret = wc_LmsKey_SetReadCb(&key.lms, lms_read_key);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_LmsKey_SetReadCb returned %d\n", ret);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
ret = wc_LmsKey_SetContext(&key.lms, (void *) CMD.key_file);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_LmsKey_SetContext returned %d\n", ret);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
ret = wc_LmsKey_Reload(&key.lms);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_LmsKey_Reload returned %d\n", ret);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
ret = wc_LmsKey_Sign(&key.lms, signature, &CMD.signature_sz, digest,
|
||||
digest_sz);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_LmsKey_Sign returned %d\n", ret);
|
||||
goto failure;
|
||||
}
|
||||
#endif /* defined(WOLFSSL_HAVE_LMS) */
|
||||
}
|
||||
|
||||
wc_FreeRng(&rng);
|
||||
|
||||
/* Sign the digest */
|
||||
ret = sign_digest(CMD.sign, CMD.hash_algo,
|
||||
signature, &CMD.signature_sz, digest, digest_sz);
|
||||
if (ret != 0) {
|
||||
printf("Signing error %d\n", ret);
|
||||
goto failure;
|
||||
|
@ -1161,36 +1160,83 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
}
|
||||
io_sz = (int)fread(signature, 1, CMD.signature_sz, f);
|
||||
fclose(f);
|
||||
if (io_sz != (int)CMD.signature_sz) {
|
||||
if (io_sz <= 0) {
|
||||
printf("Error reading file %s\n", CMD.signature_file);
|
||||
goto failure;
|
||||
}
|
||||
CMD.signature_sz = io_sz;
|
||||
}
|
||||
|
||||
/* Signing Policy */
|
||||
if (CMD.policy_sign) {
|
||||
printf("Opening signature file %s\n",
|
||||
CMD.policy_signature_file);
|
||||
/* Policy is always SHA2-256 */
|
||||
digest_sz = HDR_SHA256_LEN;
|
||||
|
||||
f = fopen(CMD.policy_signature_file, "rb");
|
||||
policy = malloc(CMD.policy_sz + sizeof(uint32_t));
|
||||
if (policy == NULL) {
|
||||
printf("Policy Signature malloc error!\n");
|
||||
goto failure;
|
||||
}
|
||||
memset(policy, 0, CMD.policy_sz);
|
||||
|
||||
/* open policy file */
|
||||
printf("Opening policy file %s\n", CMD.policy_file);
|
||||
f = fopen(CMD.policy_file, "rb");
|
||||
if (f == NULL) {
|
||||
printf("Open signature file %s failed\n",
|
||||
CMD.policy_signature_file);
|
||||
printf("Open policy digest file %s failed\n", CMD.policy_file);
|
||||
goto failure;
|
||||
}
|
||||
io_sz = (int)fread(policy_signature, 1, CMD.signature_sz, f);
|
||||
/* policy file starts with 4 byte PCR mask */
|
||||
io_sz = (int)fread(policy, 1, sizeof(uint32_t), f);
|
||||
if (io_sz != sizeof(uint32_t)) {
|
||||
printf("Error reading file %s\n", CMD.policy_file);
|
||||
fclose(f);
|
||||
if (io_sz != (int)CMD.signature_sz) {
|
||||
printf("Error reading file %s\n",
|
||||
CMD.policy_signature_file);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (!CMD.manual_sign) {
|
||||
/* in normal sign mode PCR digest (32 bytes) */
|
||||
io_sz = (int)fread(digest, 1, digest_sz, f);
|
||||
fclose(f);
|
||||
if (io_sz != (int)digest_sz) {
|
||||
printf("Error reading file %s\n", CMD.policy_file);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
printf("Signing the policy digest...\n");
|
||||
#ifdef DEBUG_SIGNTOOL
|
||||
printf("Policy Digest %d\n", digest_sz);
|
||||
WOLFSSL_BUFFER(digest, digest_sz);
|
||||
#endif
|
||||
|
||||
/* Policy is always SHA2-256 */
|
||||
ret = sign_digest(CMD.sign, HASH_SHA256,
|
||||
policy + sizeof(uint32_t), &CMD.policy_sz,
|
||||
digest, digest_sz);
|
||||
if (ret != 0) {
|
||||
printf("Signing policy error %d\n", ret);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* in manual mode PCR signature */
|
||||
io_sz = (int)fread(policy, 1, CMD.policy_sz, f);
|
||||
fclose(f);
|
||||
if (io_sz <= 0) {
|
||||
printf("Error reading file %s\n", CMD.policy_file);
|
||||
goto failure;
|
||||
}
|
||||
CMD.policy_sz = io_sz;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SIGNTOOL
|
||||
printf("Signature %d\n", CMD.signature_sz);
|
||||
WOLFSSL_BUFFER(signature, CMD.signature_sz);
|
||||
if (CMD.manual_sign && CMD.policy_sign) {
|
||||
printf("Policy Signature %d\n", CMD.signature_sz);
|
||||
WOLFSSL_BUFFER(policy_signature, CMD.signature_sz);
|
||||
if (CMD.policy_sign) {
|
||||
printf("PCR Mask 0x%08x\n", *((uint32_t*)policy));
|
||||
printf("Policy Signature %d\n", CMD.policy_sz);
|
||||
WOLFSSL_BUFFER(policy + sizeof(uint32_t), CMD.policy_sz);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1198,9 +1244,10 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
header_append_tag(header, &header_idx, HDR_SIGNATURE, CMD.signature_sz,
|
||||
signature);
|
||||
|
||||
if (CMD.manual_sign && CMD.policy_sign) {
|
||||
if (CMD.policy_sign) {
|
||||
/* Add policy signature to header */
|
||||
header_append_tag(header, &header_idx, HDR_POLICY_SIGNATURE,
|
||||
CMD.signature_sz, policy_signature);
|
||||
CMD.policy_sz + sizeof(uint32_t), policy);
|
||||
}
|
||||
} /* end if(sign != NO_SIGN) */
|
||||
|
||||
|
@ -1322,6 +1369,8 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
fclose(f2);
|
||||
fclose(f);
|
||||
failure:
|
||||
if (policy)
|
||||
free(policy);
|
||||
if (header)
|
||||
free(header);
|
||||
return ret;
|
||||
|
@ -1697,7 +1746,7 @@ int main(int argc, char** argv)
|
|||
CMD.sign = SIGN_RSA4096;
|
||||
sign_str = "RSA4096";
|
||||
}
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#ifdef WOLFSSL_HAVE_LMS
|
||||
else if (strcmp(argv[i], "--lms") == 0) {
|
||||
CMD.sign = SIGN_LMS;
|
||||
sign_str = "LMS";
|
||||
|
@ -1753,8 +1802,9 @@ int main(int argc, char** argv)
|
|||
CMD.delta = 1;
|
||||
CMD.delta_base_file = argv[++i];
|
||||
}
|
||||
else if (strcmp(argv[i], "--policy-signed") == 0) {
|
||||
else if (strcmp(argv[i], "--policy") == 0) {
|
||||
CMD.policy_sign = 1;
|
||||
CMD.policy_file = argv[++i];
|
||||
}
|
||||
else {
|
||||
i--;
|
||||
|
@ -1768,10 +1818,6 @@ int main(int argc, char** argv)
|
|||
CMD.fw_version = argv[i+3];
|
||||
if (CMD.manual_sign) {
|
||||
CMD.signature_file = argv[i+4];
|
||||
|
||||
if (CMD.policy_sign) {
|
||||
CMD.policy_signature_file = argv[i+5];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CMD.image_file = argv[i+1];
|
||||
|
@ -1877,7 +1923,7 @@ int main(int argc, char** argv)
|
|||
CMD.header_sz = 1024;
|
||||
CMD.signature_sz = 512;
|
||||
}
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#ifdef WOLFSSL_HAVE_LMS
|
||||
else if (CMD.sign == SIGN_LMS) {
|
||||
int lms_ret = 0;
|
||||
word32 sig_sz = 0;
|
||||
|
@ -1912,7 +1958,7 @@ int main(int argc, char** argv)
|
|||
CMD.header_sz = 2 * sig_sz;
|
||||
CMD.signature_sz = sig_sz;
|
||||
}
|
||||
#endif /* defined(WOLFSSL_HAVE_LMS) */
|
||||
#endif /* WOLFSSL_HAVE_LMS */
|
||||
|
||||
if (((CMD.sign != NO_SIGN) && (CMD.signature_sz == 0)) ||
|
||||
CMD.header_sz == 0) {
|
||||
|
@ -1959,7 +2005,7 @@ int main(int argc, char** argv)
|
|||
wc_FreeRsaKey(&key.rsa);
|
||||
#endif
|
||||
} else if (CMD.sign == SIGN_LMS) {
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#ifdef WOLFSSL_HAVE_LMS
|
||||
wc_LmsKey_Free(&key.lms);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -101,7 +101,6 @@
|
|||
#define NO_PWDBASED
|
||||
#define NO_WRITEV
|
||||
#define NO_FILESYSTEM
|
||||
#define NO_MAIN_DRIVER
|
||||
#define NO_OLD_RNGNAME
|
||||
#define NO_WOLFSSL_DIR
|
||||
#define WOLFSSL_NO_SOCK
|
||||
|
|
|
@ -20,23 +20,23 @@ RENODE_BINASSEMBLE=tools/bin-assemble/bin-assemble
|
|||
LMS_OPTS=LMS_LEVELS=2 LMS_HEIGHT=5 LMS_WINTERNITZ=8 WOLFBOOT_SMALL_STACK=0 \
|
||||
IMAGE_SIGNATURE_SIZE=2644 IMAGE_HEADER_SIZE=5288
|
||||
|
||||
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/keygen)","")
|
||||
KEYGEN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/keygen
|
||||
else
|
||||
# python version only supported using
|
||||
# KEYGEN_TOOL="python3 $(WOLFBOOT_ROOT)/tools/keytools/keygen.py"
|
||||
ifeq ("$(KEYGEN_TOOL)","")
|
||||
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/keygen.exe)","")
|
||||
KEYGEN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/keygen.exe
|
||||
else
|
||||
KEYGEN_TOOL=python3 $(WOLFBOOT_ROOT)/tools/keytools/keygen.py
|
||||
KEYGEN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/keygen
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/sign)","")
|
||||
SIGN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/sign
|
||||
else
|
||||
# python version only supported using
|
||||
# SIGN_TOOL="python3 $(WOLFBOOT_ROOT)/tools/keytools/sign.py"
|
||||
ifeq ("$(SIGN_TOOL)","")
|
||||
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/sign.exe)","")
|
||||
SIGN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/sign.exe
|
||||
else
|
||||
SIGN_TOOL=python3 $(WOLFBOOT_ROOT)/tools/keytools/sign.py
|
||||
SIGN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/sign
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -8,23 +8,23 @@ SPI_OPTIONS=SPI_FLASH=1 WOLFBOOT_PARTITION_SIZE=0x80000 WOLFBOOT_PARTITION_UPDAT
|
|||
SIGN_ARGS=
|
||||
SIGN_ENC_ARGS=
|
||||
|
||||
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/keygen)","")
|
||||
KEYGEN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/keygen
|
||||
else
|
||||
# python version only supported using
|
||||
# KEYGEN_TOOL="python3 $(WOLFBOOT_ROOT)/tools/keytools/keygen.py"
|
||||
ifeq ("$(KEYGEN_TOOL)","")
|
||||
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/keygen.exe)","")
|
||||
KEYGEN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/keygen.exe
|
||||
else
|
||||
KEYGEN_TOOL=python3 $(WOLFBOOT_ROOT)/tools/keytools/keygen.py
|
||||
KEYGEN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/keygen
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/sign)","")
|
||||
SIGN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/sign
|
||||
else
|
||||
# python version only supported using
|
||||
# SIGN_TOOL="python3 $(WOLFBOOT_ROOT)/tools/keytools/sign.py"
|
||||
ifeq ("$(SIGN_TOOL)","")
|
||||
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/sign.exe)","")
|
||||
SIGN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/sign.exe
|
||||
else
|
||||
SIGN_TOOL=python3 $(WOLFBOOT_ROOT)/tools/keytools/sign.py
|
||||
SIGN_TOOL=$(WOLFBOOT_ROOT)/tools/keytools/sign
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -74,7 +74,7 @@ $(BINASSEMBLE):
|
|||
test-size: FORCE
|
||||
$(Q)make clean
|
||||
$(Q)make wolfboot.bin
|
||||
$(Q)FP=`$(SIZE) -A wolfboot.elf | awk -e ' /Total/ {print $$2;}'`; echo SIZE: $$FP LIMIT: $$LIMIT; test $$FP -le $$LIMIT
|
||||
$(Q)FP=`$(SIZE) -A wolfboot.elf | awk ' /Total/ {print $$2;}'`; echo SIZE: $$FP LIMIT: $$LIMIT; test $$FP -le $$LIMIT
|
||||
|
||||
# Testbed actions
|
||||
#
|
||||
|
@ -941,29 +941,29 @@ test-all: clean
|
|||
|
||||
|
||||
test-size-all:
|
||||
make test-size SIGN=NONE LIMIT=4722
|
||||
make test-size SIGN=NONE LIMIT=4730
|
||||
make keysclean
|
||||
make test-size SIGN=ED25519 LIMIT=11398
|
||||
make keysclean
|
||||
make test-size SIGN=ECC256 LIMIT=22266
|
||||
make test-size SIGN=ECC256 LIMIT=22270
|
||||
make keysclean
|
||||
make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13702
|
||||
make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13706
|
||||
make keysclean
|
||||
make test-size SIGN=RSA2048 LIMIT=11182
|
||||
make test-size SIGN=RSA2048 LIMIT=11186
|
||||
make keysclean
|
||||
make test-size SIGN=RSA2048 NO_ASM=1 LIMIT=11162
|
||||
make test-size SIGN=RSA2048 NO_ASM=1 LIMIT=11166
|
||||
make keysclean
|
||||
make test-size SIGN=RSA4096 LIMIT=11546
|
||||
make test-size SIGN=RSA4096 LIMIT=11550
|
||||
make keysclean
|
||||
make test-size SIGN=RSA4096 NO_ASM=1 LIMIT=11462
|
||||
make test-size SIGN=RSA4096 NO_ASM=1 LIMIT=11466
|
||||
make keysclean
|
||||
make test-size SIGN=ECC384 LIMIT=17562
|
||||
make test-size SIGN=ECC384 LIMIT=17566
|
||||
make keysclean
|
||||
make test-size SIGN=ECC384 NO_ASM=1 LIMIT=15172
|
||||
make keysclean
|
||||
make test-size SIGN=ED448 LIMIT=13414
|
||||
make keysclean
|
||||
make test-size SIGN=RSA3072 LIMIT=11382
|
||||
make test-size SIGN=RSA3072 LIMIT=11386
|
||||
make keysclean
|
||||
make test-size SIGN=RSA3072 NO_ASM=1 LIMIT=11254
|
||||
make test-size SIGN=RSA3072 NO_ASM=1 LIMIT=11258
|
||||
make keysclean
|
||||
|
|
|
@ -13,16 +13,19 @@ WOLFBOOTDIR = ../..
|
|||
WOLFDIR = $(WOLFBOOTDIR)/lib/wolfssl/
|
||||
WOLFTPMDIR = $(WOLFBOOTDIR)/lib/wolfTPM/
|
||||
CFLAGS = -Wall -Wextra -Werror
|
||||
CFLAGS += -I. -DWOLFSSL_USER_SETTINGS -DWOLFTPM_USER_SETTINGS -I$(WOLFDIR) -I$(WOLFTPMDIR) -I$(WOLFBOOTDIR)/include
|
||||
CFLAGS += -DWOLFSSL_USER_SETTINGS -DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM
|
||||
CFLAGS += -I. -I$(WOLFDIR) -I$(WOLFTPMDIR) -I$(WOLFBOOTDIR)/include
|
||||
LDFLAGS =
|
||||
OBJDIR = ./
|
||||
|
||||
# option variables
|
||||
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE -fsanitize=address
|
||||
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_WOLFTPM -DDEBUG_WOLFSSL -DWOLFTPM_DEBUG_VERBOSE
|
||||
SANITIZE_FLAGS = -fsanitize=address
|
||||
OPTIMIZE = -O2
|
||||
|
||||
# Options
|
||||
#CFLAGS+=$(DEBUG_FLAGS)
|
||||
#CFLAGS+=$(SANITIZE_FLAGS)
|
||||
CFLAGS+=$(OPTIMIZE)
|
||||
|
||||
ifeq ($(TARGET),sim)
|
||||
|
@ -68,11 +71,12 @@ vpath %.c $(WOLFDIR)/wolfcrypt/src/
|
|||
vpath %.c $(WOLFBOOTDIR)/src/
|
||||
vpath %.c $(WOLFTPMDIR)/src/
|
||||
vpath %.c $(WOLFTPMDIR)/hal/
|
||||
vpath %.c $(WOLFTPMDIR)/examples/pcr
|
||||
vpath %.c ./
|
||||
|
||||
.PHONY: clean all
|
||||
|
||||
all: rot
|
||||
all: rot policy_create pcr_extend pcr_read pcr_reset
|
||||
|
||||
debug: CFLAGS+=$(DEBUG_FLAGS)
|
||||
debug: all
|
||||
|
@ -94,5 +98,21 @@ rot: $(OBJS_VIRT) rot.o
|
|||
@echo "Building Root of Trust (ROT) tool"
|
||||
$(Q)$(LD) -o $@ $@.o $(OBJS_VIRT) $(LDFLAGS)
|
||||
|
||||
policy_create: $(OBJS_VIRT) policy_create.o
|
||||
@echo "Building Policy Creation Tool"
|
||||
$(Q)$(LD) -o $@ $@.o $(OBJS_VIRT) $(LDFLAGS)
|
||||
|
||||
pcr_extend: $(OBJS_VIRT) $(WOLFTPMDIR)/examples/pcr/extend.o
|
||||
@echo "Building PCR Extend Tool"
|
||||
$(Q)$(LD) -o $@ $(WOLFTPMDIR)/examples/pcr/extend.o $(OBJS_VIRT) $(LDFLAGS)
|
||||
|
||||
pcr_read: $(OBJS_VIRT) $(WOLFTPMDIR)/examples/pcr/read_pcr.o
|
||||
@echo "Building PCR Read Tool"
|
||||
$(Q)$(LD) -o $@ $(WOLFTPMDIR)/examples/pcr/read_pcr.o $(OBJS_VIRT) $(LDFLAGS)
|
||||
|
||||
pcr_reset: $(OBJS_VIRT) $(WOLFTPMDIR)/examples/pcr/reset.o
|
||||
@echo "Building PCR Reset Tool"
|
||||
$(Q)$(LD) -o $@ $(WOLFTPMDIR)/examples/pcr/reset.o $(OBJS_VIRT) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f rot *.o
|
||||
rm -f rot policy_create pcr_extend pcr_read pcr_reset *.o
|
||||
|
|
|
@ -4,7 +4,7 @@ Tools to help with TPM setup.
|
|||
|
||||
For wolfBoot TPM features see (docs/TPM.md)[/docs/TPM.md].
|
||||
|
||||
# Secure Boot Root of Trust (ROT)
|
||||
## Secure Boot Root of Trust (ROT)
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -13,3 +13,18 @@ Examples:
|
|||
* `./tools/tpm/rot -write -lock`: Write and lock the NV
|
||||
* `./tools/tpm/rot -write -sha384`: Write NV using SHA2-384
|
||||
* `./tools/tpm/rot -write -auth=test`: Use password for NV access
|
||||
|
||||
## Sealing / Unsealing
|
||||
|
||||
A PCR policy is signed with the `tools/keytool/sign` tool using the --policy argument.
|
||||
The policy file comes from the `tools/tpm/policy_create` tool and contains a 4-byte PCR mask and PCR digest.
|
||||
The authorization for the sealing/unsealing comes from the signed policy and its public key (stored in `keystore.c`).
|
||||
Typically PCR's 0-15 are used for boot measurements and sealing/unsealing, since they can only be reset on a reboot. The PCR 16 is used for testing.
|
||||
|
||||
Examples:
|
||||
|
||||
* `./tools/tpm/pcr_reset 16`: Reset PCR 16
|
||||
* `./tools/tpm/pcr_extend 16 aaa.bin`: Extend PCR 16 with the SHA2-256 hash of "aaa"
|
||||
* `./tools/tpm/policy_create -pcr=16 -pcrdigest=eca4e8eda468b8667244ae972b8240d3244ea72341b2bf2383e79c66643bbecc -out=policy.bin`: Create a policy.bin file with 4-byte PCR mask and 32-byte PCR digest.
|
||||
* `./tools/keytools/sign --ecc256 --policy policy.bin test-app/image.elf wolfboot_signing_private_key.der 1`: Sign the PCR policy and include in the `HDR_POLICY_SIGNATURE` image header.
|
||||
* `make POLICY_FILE=policy.bin`: This will perform a build and include the policy file argument to the sign tool. This can also go into the .config file.
|
||||
|
|
|
@ -0,0 +1,273 @@
|
|||
/* policy_create.c
|
||||
*
|
||||
* Copyright (C) 2006-2023 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
*
|
||||
* wolfTPM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfTPM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/* Tool for creating a policy digest file that is then signed by the key tool
|
||||
* and included in the image header using HDR_POLICY_SIGNATURE.
|
||||
*/
|
||||
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/wolfcrypt/ecc.h>
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
#include <wolftpm/tpm2_wrap.h>
|
||||
#include <hal/tpm_io.h>
|
||||
#include "keystore.h"
|
||||
#include "tpm.h"
|
||||
|
||||
#define DEFAULT_PCR 16
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Expected usage:\n");
|
||||
printf("./examples/pcr/policy_create [-pcr=/-pcrmask] [-pcrdigest=] [-out=]\n");
|
||||
printf("* -pcr=index: SHA2-256 PCR index < 24 (multiple can be supplied) (default %d)\n", DEFAULT_PCR);
|
||||
printf("* -pcrmask=0x00000000: PCR mask (or -pcr= args)\n");
|
||||
printf("* -pcrdigest=hexstr: PCR Digest (default=Read actual PCR's)\n");
|
||||
printf("* -out=file: Policy Digest to sign (default policy.bin)\n");
|
||||
}
|
||||
|
||||
int writeBin(const char* filename, const uint8_t*buf, word32 bufSz)
|
||||
{
|
||||
int rc = TPM_RC_FAILURE;
|
||||
|
||||
if (filename == NULL || buf == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
XFILE fp = NULL;
|
||||
size_t fileSz = 0;
|
||||
|
||||
fp = XFOPEN(filename, "wt");
|
||||
if (fp != XBADFILE) {
|
||||
fileSz = XFWRITE(buf, 1, bufSz, fp);
|
||||
/* sanity check */
|
||||
if (fileSz == (word32)bufSz) {
|
||||
rc = TPM_RC_SUCCESS;
|
||||
}
|
||||
printf("Wrote %d bytes to %s\n", (int)fileSz, filename);
|
||||
XFCLOSE(fp);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static signed char hexCharToByte(signed char ch)
|
||||
{
|
||||
signed char ret = (signed char)ch;
|
||||
if (ret >= '0' && ret <= '9')
|
||||
ret -= '0';
|
||||
else if (ret >= 'A' && ret <= 'F')
|
||||
ret -= 'A' - 10;
|
||||
else if (ret >= 'a' && ret <= 'f')
|
||||
ret -= 'a' - 10;
|
||||
else
|
||||
ret = -1; /* error case - return code must be signed */
|
||||
return ret;
|
||||
}
|
||||
static int hexToByte(const char *hex, unsigned char *output, unsigned long sz)
|
||||
{
|
||||
int outSz = 0;
|
||||
word32 i;
|
||||
for (i = 0; i < sz; i+=2) {
|
||||
signed char ch1, ch2;
|
||||
ch1 = hexCharToByte(hex[i]);
|
||||
ch2 = hexCharToByte(hex[i+1]);
|
||||
if ((ch1 < 0) || (ch2 < 0)) {
|
||||
return -1;
|
||||
}
|
||||
output[outSz++] = (unsigned char)((ch1 << 4) + ch2);
|
||||
}
|
||||
return outSz;
|
||||
}
|
||||
static void printHexString(const unsigned char* bin, unsigned long sz,
|
||||
unsigned long maxLine)
|
||||
{
|
||||
unsigned long i;
|
||||
printf("\t");
|
||||
if (maxLine == 0) maxLine = sz;
|
||||
for (i = 0; i < sz; i++) {
|
||||
printf("%02x", bin[i]);
|
||||
if (((i+1) % maxLine) == 0 && i+1 != sz)
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void tpm_mask_sel_pcr(uint32_t pcrMask, uint8_t* pcrArray,
|
||||
uint32_t* pcrArraySz)
|
||||
{
|
||||
int i;
|
||||
*pcrArraySz = 0;
|
||||
for (i=0; i<IMPLEMENTATION_PCR; i++) {
|
||||
if (pcrMask & (1 << i)) {
|
||||
pcrArray[(*pcrArraySz)++] = i;
|
||||
/* make sure we have room */
|
||||
if (*pcrArraySz >= PCR_SELECT_MAX*2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int TPM2_PCR_Policy_Create(TPM_ALG_ID pcrAlg,
|
||||
uint8_t* pcrArray, word32 pcrArraySz,
|
||||
const char* outFile,
|
||||
uint8_t* pcrDigest, word32 pcrDigestSz,
|
||||
uint8_t* policyRef, word32 policyRefSz)
|
||||
{
|
||||
int rc = -1, i;
|
||||
word32 pcrMask = 0;
|
||||
byte policy[sizeof(pcrMask) + WC_MAX_DIGEST_SIZE]; /* pcrmask + digest */
|
||||
word32 policySz = 0;
|
||||
byte* digest = &policy[sizeof(pcrMask)];
|
||||
word32 digestSz;
|
||||
|
||||
printf("Policy Create Tool\n");
|
||||
|
||||
/* calculate pcrMask */
|
||||
printf("PCR Index(s) (%s): ", TPM2_GetAlgName(pcrAlg));
|
||||
for (i = 0; i < (int)pcrArraySz; i++) {
|
||||
printf("%d ", pcrArray[i]);
|
||||
pcrMask |= (1 << pcrArray[i]);
|
||||
}
|
||||
printf(" (mask 0x%08x)\n", pcrMask);
|
||||
XMEMSET(policy, 0, sizeof(policy));
|
||||
XMEMCPY(policy, &pcrMask, sizeof(pcrMask));
|
||||
policySz += (word32)sizeof(pcrMask);
|
||||
|
||||
/* PCR Hash - Use provided hash or read PCR's and get hash */
|
||||
if (pcrDigestSz == 0) {
|
||||
WOLFTPM2_DEV dev;
|
||||
XMEMSET(&dev, 0, sizeof(WOLFTPM2_DEV));
|
||||
rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
|
||||
if (rc == 0) {
|
||||
rc = wolfTPM2_PCRGetDigest(&dev, pcrAlg, pcrArray, pcrArraySz,
|
||||
pcrDigest, &pcrDigestSz);
|
||||
wolfTPM2_Cleanup(&dev);
|
||||
}
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
printf("Error getting PCR's! 0x%x: %s\n", rc, TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
printf("PCR Digest (%d bytes):\n", pcrDigestSz);
|
||||
printHexString(pcrDigest, pcrDigestSz, 0);
|
||||
|
||||
/* Build PCR Policy to Sign */
|
||||
digestSz = TPM2_GetHashDigestSize(pcrAlg);
|
||||
/* Note: digest is used an input here to allow chaining policies,
|
||||
* but for this use-case should be zero'd */
|
||||
rc = wolfTPM2_PolicyPCRMake(pcrAlg, pcrArray, pcrArraySz,
|
||||
pcrDigest, pcrDigestSz, digest, &digestSz);
|
||||
if (rc == 0) {
|
||||
/* Add policyRef (if blank just re-hash) */
|
||||
rc = wolfTPM2_PolicyRefMake(pcrAlg, digest, &digestSz,
|
||||
policyRef, policyRefSz);
|
||||
}
|
||||
if (rc == 0) {
|
||||
policySz += digestSz;
|
||||
|
||||
printf("PCR Mask (0x%08x) and PCR Policy Digest (%d bytes):\n",
|
||||
pcrMask, digestSz);
|
||||
printHexString(digest, digestSz, 0);
|
||||
|
||||
/* Write pcrMask (4) and digest */
|
||||
writeBin(outFile, policy, policySz);
|
||||
}
|
||||
|
||||
exit:
|
||||
if (rc != 0) {
|
||||
printf("Failure 0x%x: %s\n", rc, wolfTPM2_GetRCString(rc));
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TPM_ALG_ID pcrAlg = WOLFBOOT_TPM_PCR_ALG;
|
||||
byte pcrArray[PCR_SELECT_MAX*2];
|
||||
word32 pcrArraySz = 0;
|
||||
const char* outFile = "policy.bin";
|
||||
byte pcrDigest[WC_MAX_DIGEST_SIZE];
|
||||
word32 pcrDigestSz = 0;
|
||||
uint8_t* policyRef = NULL; /* optional nonce */
|
||||
word32 policyRefSz = 0;
|
||||
word32 pcrMask = 0;
|
||||
|
||||
if (argc >= 2) {
|
||||
if (XSTRCMP(argv[1], "-?") == 0 ||
|
||||
XSTRCMP(argv[1], "-h") == 0 ||
|
||||
XSTRCMP(argv[1], "--help") == 0) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (argc > 1) {
|
||||
if (XSTRNCMP(argv[argc-1], "-pcr=", XSTRLEN("-pcr=")) == 0) {
|
||||
const char* pcrStr = argv[argc-1] + XSTRLEN("-pcr=");
|
||||
byte pcrIndex = (byte)XATOI(pcrStr);
|
||||
if (pcrIndex > PCR_LAST) {
|
||||
printf("PCR index is out of range (0-23)\n");
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
pcrArray[pcrArraySz++] = pcrIndex;
|
||||
}
|
||||
else if (XSTRNCMP(argv[argc-1], "-pcrmask=", XSTRLEN("-pcrmask=")) == 0) {
|
||||
const char* pcrMaskStr = argv[argc-1] + XSTRLEN("-pcrmask=");
|
||||
pcrMask = (word32)XSTRTOL(pcrMaskStr, NULL, 0);
|
||||
}
|
||||
else if (XSTRNCMP(argv[argc-1], "-pcrdigest=", XSTRLEN("-pcrdigest=")) == 0) {
|
||||
const char* hashHexStr = argv[argc-1] + XSTRLEN("-pcrdigest=");
|
||||
int hashHexStrLen = (int)XSTRLEN(hashHexStr);
|
||||
if (hashHexStrLen > (int)sizeof(pcrDigest)*2+1)
|
||||
pcrDigestSz = -1;
|
||||
else
|
||||
pcrDigestSz = hexToByte(hashHexStr, pcrDigest, hashHexStrLen);
|
||||
if (pcrDigestSz <= 0) {
|
||||
fprintf(stderr, "Invalid PCR hash length\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (XSTRNCMP(argv[argc-1], "-out=",
|
||||
XSTRLEN("-out=")) == 0) {
|
||||
outFile = argv[argc-1] + XSTRLEN("-out=");
|
||||
}
|
||||
else {
|
||||
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
|
||||
}
|
||||
argc--;
|
||||
}
|
||||
|
||||
/* Determine PCR's based on mask or default (if none set) */
|
||||
if (pcrArraySz == 0) {
|
||||
if (pcrMask == 0) {
|
||||
pcrArray[pcrArraySz++] = DEFAULT_PCR;
|
||||
}
|
||||
else {
|
||||
tpm_mask_sel_pcr(pcrMask, pcrArray, &pcrArraySz);
|
||||
}
|
||||
}
|
||||
|
||||
return TPM2_PCR_Policy_Create(pcrAlg,
|
||||
pcrArray, pcrArraySz, outFile,
|
||||
pcrDigest, pcrDigestSz, policyRef, policyRefSz);
|
||||
}
|
|
@ -24,7 +24,8 @@
|
|||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
#include <wolftpm/tpm2_wrap.h>
|
||||
#include <hal/tpm_io.h>
|
||||
#include <keystore.h>
|
||||
#include "keystore.h"
|
||||
#include "tpm.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -32,13 +33,11 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define TPM2_DEMO_NV_SECURE_ROT_INDEX 0x01400200
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Expected usage:\n");
|
||||
printf("./tools/tpm/rot [-nvindex] [-write] [-auth] [-sha384] [-lock]\n");
|
||||
printf("* -nvindex=[handle] (default 0x%x)\n", TPM2_DEMO_NV_SECURE_ROT_INDEX);
|
||||
printf("./tools/tpm/rot [-nvbase] [-write] [-auth] [-sha384] [-lock]\n");
|
||||
printf("* -nvbase=[handle] (default 0x%x)\n", WOLFBOOT_TPM_KEYSTORE_NV_BASE);
|
||||
printf("* -write: Using keystore.c API's hashes each public key and stores into NV\n");
|
||||
printf("* -auth=password: Optional password for NV\n");
|
||||
printf("* -sha384: Use SHA2-384 (default is SHA2-256)\n");
|
||||
|
@ -48,7 +47,7 @@ static void usage(void)
|
|||
printf("\t./tools/tpm/rot -write\n");
|
||||
}
|
||||
|
||||
int TPM2_Boot_SecureROT_Example(TPMI_RH_NV_AUTH authHandle, word32 nvIndex,
|
||||
static int TPM2_Boot_SecureROT_Example(TPMI_RH_NV_AUTH authHandle, word32 nvBaseIdx,
|
||||
enum wc_HashType hashType, int doWrite, int doLock,
|
||||
const char *authBuf, int authBufSz)
|
||||
{
|
||||
|
@ -93,17 +92,17 @@ int TPM2_Boot_SecureROT_Example(TPMI_RH_NV_AUTH authHandle, word32 nvIndex,
|
|||
if (rc != 0) goto exit;
|
||||
|
||||
printf("NV Auth (%d)\n", authBufSz);
|
||||
TPM2_PrintBin((const byte*)authBuf, authBufSz);
|
||||
TPM2_PrintBin((const uint8_t*)authBuf, authBufSz);
|
||||
|
||||
for (id = 0; id < keystore_num_pubkeys(); id++) {
|
||||
TPM_HANDLE handle = nvIndex + id;
|
||||
TPM_HANDLE handle = nvBaseIdx + id;
|
||||
uint32_t keyType = keystore_get_key_type(id);
|
||||
int bufSz = keystore_get_size(id);
|
||||
byte *buf = keystore_get_buffer(id);
|
||||
uint8_t*buf = keystore_get_buffer(id);
|
||||
|
||||
(void)keyType; /* not used */
|
||||
|
||||
printf("Computing keystore has for index %d\n", id);
|
||||
printf("Computing keystore hash for index %d\n", id);
|
||||
|
||||
/* hash public key */
|
||||
digestSz = wc_HashGetDigestSize(hashType);
|
||||
|
@ -124,7 +123,7 @@ int TPM2_Boot_SecureROT_Example(TPMI_RH_NV_AUTH authHandle, word32 nvIndex,
|
|||
|
||||
/* Create NV - NV struct populated */
|
||||
rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, handle,
|
||||
nvAttributes, digestSz, (const byte*)authBuf, authBufSz);
|
||||
nvAttributes, digestSz, (const uint8_t*)authBuf, authBufSz);
|
||||
if (rc == TPM_RC_NV_DEFINED) {
|
||||
printf("Warning: NV Index 0x%x already exists!\n", handle);
|
||||
rc = 0;
|
||||
|
@ -192,7 +191,7 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
/* use platform handle to prevent TPM2_Clear from removing */
|
||||
TPMI_RH_NV_AUTH authHandle = TPM_RH_PLATFORM;
|
||||
word32 nvIndex = TPM2_DEMO_NV_SECURE_ROT_INDEX;
|
||||
word32 nvBaseIdx = WOLFBOOT_TPM_KEYSTORE_NV_BASE;
|
||||
int doWrite = 0, doLock = 0;
|
||||
enum wc_HashType hashType = WC_HASH_TYPE_SHA256;
|
||||
const char* authBuf = NULL;
|
||||
|
@ -207,17 +206,17 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
while (argc > 1) {
|
||||
if (XSTRNCMP(argv[argc-1], "-nvindex=", XSTRLEN("-nvindex=")) == 0) {
|
||||
const char* nvIndexStr = argv[argc-1] + XSTRLEN("-nvindex=");
|
||||
nvIndex = (word32)XSTRTOL(nvIndexStr, NULL, 0);
|
||||
if (XSTRNCMP(argv[argc-1], "-nvbase=", XSTRLEN("-nvbase=")) == 0) {
|
||||
const char* nvBaseIdxStr = argv[argc-1] + XSTRLEN("-nvbase=");
|
||||
nvBaseIdx = (word32)XSTRTOL(nvBaseIdxStr, NULL, 0);
|
||||
if (!(authHandle == TPM_RH_PLATFORM && (
|
||||
nvIndex > TPM_20_PLATFORM_MFG_NV_SPACE &&
|
||||
nvIndex < TPM_20_OWNER_NV_SPACE)) &&
|
||||
nvBaseIdx > TPM_20_PLATFORM_MFG_NV_SPACE &&
|
||||
nvBaseIdx < TPM_20_OWNER_NV_SPACE)) &&
|
||||
!(authHandle == TPM_RH_OWNER && (
|
||||
nvIndex > TPM_20_OWNER_NV_SPACE &&
|
||||
nvIndex < TPM_20_TCG_NV_SPACE)))
|
||||
nvBaseIdx > TPM_20_OWNER_NV_SPACE &&
|
||||
nvBaseIdx < TPM_20_TCG_NV_SPACE)))
|
||||
{
|
||||
fprintf(stderr, "Invalid NV Index %s\n", nvIndexStr);
|
||||
fprintf(stderr, "Invalid NV Index %s\n", nvBaseIdxStr);
|
||||
fprintf(stderr, "\tPlatform Range: 0x%x -> 0x%x\n",
|
||||
TPM_20_PLATFORM_MFG_NV_SPACE, TPM_20_OWNER_NV_SPACE);
|
||||
fprintf(stderr, "\tOwner Range: 0x%x -> 0x%x\n",
|
||||
|
@ -247,7 +246,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
return TPM2_Boot_SecureROT_Example(
|
||||
authHandle,
|
||||
nvIndex,
|
||||
nvBaseIdx,
|
||||
hashType,
|
||||
doWrite,
|
||||
doLock,
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
#define NO_DES3
|
||||
#define NO_PWDBASED
|
||||
#define NO_WRITEV
|
||||
#define NO_MAIN_DRIVER
|
||||
#define NO_OLD_RNGNAME
|
||||
#define NO_WOLFSSL_DIR
|
||||
#define WOLFSSL_NO_SOCK
|
||||
|
|
Loading…
Reference in New Issue