mirror of https://github.com/wolfSSL/wolfBoot.git
Added support for storing sealed blobs into NV. Refactor the TPM signature verify to use existing load public key function and generic verify hash TPM function. Added support for RSA sign with ASN.1 encoding (Example: `SIGN=RSA2048ENC`).
parent
490286be7d
commit
2349a68e76
|
@ -34,7 +34,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
arch: host
|
arch: host
|
||||||
config-file: ./config/examples/sim-tpm.config
|
config-file: ./config/examples/sim-tpm.config
|
||||||
make-args: SIGN=RSA2048 HASH=SHA256
|
make-args: SIGN=RSA2048ENC HASH=SHA256
|
||||||
|
|
||||||
|
|
||||||
sim_tpm_measured_ecc256:
|
sim_tpm_measured_ecc256:
|
||||||
|
@ -107,5 +107,5 @@ jobs:
|
||||||
with:
|
with:
|
||||||
arch: host
|
arch: host
|
||||||
config-file: ./config/examples/sim-tpm-seal.config
|
config-file: ./config/examples/sim-tpm-seal.config
|
||||||
make-args: SIGN=RSA2048 HASH=SHA256 POLICY_FILE=policy.bin
|
make-args: SIGN=RSA2048ENC HASH=SHA256 POLICY_FILE=policy.bin
|
||||||
authstr: TestAuth
|
authstr: TestAuth
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -21,6 +21,7 @@ V?=0
|
||||||
DEBUG?=0
|
DEBUG?=0
|
||||||
DEBUG_UART?=0
|
DEBUG_UART?=0
|
||||||
LIBS=
|
LIBS=
|
||||||
|
SIGN_ALG=
|
||||||
|
|
||||||
OBJS:= \
|
OBJS:= \
|
||||||
./hal/$(TARGET).o \
|
./hal/$(TARGET).o \
|
||||||
|
@ -207,7 +208,8 @@ wolfboot_stage1.bin: wolfboot.bin stage1/loader_stage1.bin
|
||||||
$(Q) cp stage1/loader_stage1.bin wolfboot_stage1.bin
|
$(Q) cp stage1/loader_stage1.bin wolfboot_stage1.bin
|
||||||
|
|
||||||
wolfboot.elf: include/target.h $(LSCRIPT) $(OBJS) $(LIBS) $(BINASSEMBLE) FORCE
|
wolfboot.elf: include/target.h $(LSCRIPT) $(OBJS) $(LIBS) $(BINASSEMBLE) FORCE
|
||||||
$(Q)(test $(SIGN) = NONE) || (grep -q $(SIGN) src/keystore.c) || (echo "Key mismatch: please run 'make distclean' to remove all keys if you want to change algorithm" && false)
|
$(Q)(test $(SIGN) = NONE) || (grep -q $(SIGN_ALG) src/keystore.c) || \
|
||||||
|
(echo "Key mismatch: please run 'make distclean' to remove all keys if you want to change algorithm" && false)
|
||||||
@echo "\t[LD] $@"
|
@echo "\t[LD] $@"
|
||||||
@echo $(OBJS) $(LIBS)
|
@echo $(OBJS) $(LIBS)
|
||||||
$(Q)$(LD) $(LDFLAGS) $(LSCRIPT_FLAGS) $(LD_START_GROUP) $(OBJS) $(LIBS) $(LD_END_GROUP) -o $@
|
$(Q)$(LD) $(LDFLAGS) $(LSCRIPT_FLAGS) $(LD_START_GROUP) $(OBJS) $(LIBS) $(LD_END_GROUP) -o $@
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
ARCH=sim
|
ARCH=sim
|
||||||
TARGET=sim
|
TARGET=sim
|
||||||
|
# note TPM requires ASN.1 encoding for RSA, so use RSA2048ENC, RSA3072ENC, RSA4096ENC
|
||||||
SIGN?=ECC256
|
SIGN?=ECC256
|
||||||
HASH?=SHA256
|
HASH?=SHA256
|
||||||
SPI_FLASH=0
|
SPI_FLASH=0
|
||||||
|
|
61
docs/TPM.md
61
docs/TPM.md
|
@ -23,7 +23,8 @@ The design uses a platform NV handle that has been locked. The NV stores a hash
|
||||||
|
|
||||||
## Cryptographic offloading
|
## Cryptographic offloading
|
||||||
|
|
||||||
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`
|
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`.
|
||||||
|
NOTE: The TPM's RSA verify requires ASN.1 encoding, so use SIGN=RSA2048ENC
|
||||||
|
|
||||||
## Measured Boot
|
## Measured Boot
|
||||||
|
|
||||||
|
@ -45,33 +46,57 @@ int wolfBoot_unseal(struct wolfBoot_image* img, int index, uint8_t* secret, int*
|
||||||
By default this index will be based on an NV Index at `(0x01400300 + index)`.
|
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`.
|
The default NV base can be overridden with `WOLFBOOT_TPM_SEAL_NV_BASE`.
|
||||||
|
|
||||||
|
NOTE: The TPM's RSA verify requires ASN.1 encoding, so use SIGN=RSA2048ENC
|
||||||
|
|
||||||
### Testing seal/unseal with simulator
|
### Testing seal/unseal with simulator
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cp config/examples/sim-tpm-seal.config .config
|
% cp config/examples/sim-tpm-seal.config .config
|
||||||
make keytools
|
% make keytools
|
||||||
make tpmtools
|
% make tpmtools
|
||||||
echo aaa > aaa.bin
|
% echo aaa > aaa.bin
|
||||||
./tools/tpm/pcr_extend 0 aaa.bin
|
% ./tools/tpm/pcr_extend 0 aaa.bin
|
||||||
./tools/tpm/policy_create -pcr=0
|
% ./tools/tpm/policy_create -pcr=0
|
||||||
# if ROT enabled
|
# if ROT enabled
|
||||||
./tools/tpm/rot -write
|
% ./tools/tpm/rot -write
|
||||||
make clean && make POLICY_FILE=policy.bin
|
% make clean && make POLICY_FILE=policy.bin
|
||||||
./wolfboot.elf get_version
|
|
||||||
Simulator assigned ./internal_flash.dd to base 0x103797000
|
% ./wolfboot.elf get_version
|
||||||
|
Simulator assigned ./internal_flash.dd to base 0x103378000
|
||||||
Mfg IBM (0), Vendor SW TPM, Fw 8217.4131 (0x163636), FIPS 140-2 1, CC-EAL4 0
|
Mfg IBM (0), Vendor SW TPM, Fw 8217.4131 (0x163636), FIPS 140-2 1, CC-EAL4 0
|
||||||
Unlocking disk...
|
Unlocking disk...
|
||||||
Boot partition: 0x103817000
|
Boot partition: 0x1033f8000
|
||||||
Image size 54400
|
Image size 54400
|
||||||
Sealing 32 bytes
|
Error 395 reading blob from NV index 1400300 (error TPM_RC_HANDLE)
|
||||||
11c6ac0ec972ae567c541750c6ecccd426f131dad3eeca5e6540d901d9f0c336
|
Error 395 unsealing secret! (TPM_RC_HANDLE)
|
||||||
Unsealed 32 bytes
|
Sealed secret does not exist!
|
||||||
11c6ac0ec972ae567c541750c6ecccd426f131dad3eeca5e6540d901d9f0c336
|
Creating new secret (32 bytes)
|
||||||
Boot partition: 0x103817000
|
430dee45553c4a8b75fbc6bcd0890765c48cab760b24b1aa6b633dc0538e0159
|
||||||
|
Wrote 210 bytes to NV index 0x1400300
|
||||||
|
Read 210 bytes from NV index 0x1400300
|
||||||
|
Secret Check 32 bytes
|
||||||
|
430dee45553c4a8b75fbc6bcd0890765c48cab760b24b1aa6b633dc0538e0159
|
||||||
|
Secret 32 bytes
|
||||||
|
430dee45553c4a8b75fbc6bcd0890765c48cab760b24b1aa6b633dc0538e0159
|
||||||
|
Boot partition: 0x1033f8000
|
||||||
Image size 54400
|
Image size 54400
|
||||||
TPM Root of Trust valid (id 0)
|
TPM Root of Trust valid (id 0)
|
||||||
Simulator assigned ./internal_flash.dd to base 0x103962000
|
Simulator assigned ./internal_flash.dd to base 0x103543000
|
||||||
|
1
|
||||||
|
|
||||||
|
% ./wolfboot.elf get_version
|
||||||
|
Simulator assigned ./internal_flash.dd to base 0x10c01c000
|
||||||
|
Mfg IBM (0), Vendor SW TPM, Fw 8217.4131 (0x163636), FIPS 140-2 1, CC-EAL4 0
|
||||||
|
Unlocking disk...
|
||||||
|
Boot partition: 0x10c09c000
|
||||||
|
Image size 54400
|
||||||
|
Read 210 bytes from NV index 0x1400300
|
||||||
|
Secret 32 bytes
|
||||||
|
430dee45553c4a8b75fbc6bcd0890765c48cab760b24b1aa6b633dc0538e0159
|
||||||
|
Boot partition: 0x10c09c000
|
||||||
|
Image size 54400
|
||||||
|
TPM Root of Trust valid (id 0)
|
||||||
|
Simulator assigned ./internal_flash.dd to base 0x10c1e7000
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,11 @@ extern WOLFTPM2_KEY wolftpm_srk;
|
||||||
int wolfBoot_tpm2_init(void);
|
int wolfBoot_tpm2_init(void);
|
||||||
void wolfBoot_tpm2_deinit(void);
|
void wolfBoot_tpm2_deinit(void);
|
||||||
|
|
||||||
|
#if defined(WOLFBOOT_TPM_VERIFY) || defined(WOLFBOOT_TPM_SEAL)
|
||||||
|
int wolfBoot_load_pubkey(struct wolfBoot_image* img, WOLFTPM2_KEY* pubKey,
|
||||||
|
TPM_ALG_ID* pAlg);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||||
int wolfBoot_check_rot(int key_slot, uint8_t* pubkey_hint);
|
int wolfBoot_check_rot(int key_slot, uint8_t* pubkey_hint);
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,12 +63,26 @@ int wolfBoot_check_rot(int key_slot, uint8_t* pubkey_hint);
|
||||||
#ifdef WOLFBOOT_TPM_SEAL
|
#ifdef WOLFBOOT_TPM_SEAL
|
||||||
int wolfBoot_get_random(uint8_t* buf, int sz);
|
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_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_build_policy(uint8_t pcrAlg, uint32_t pcrMask,
|
||||||
int wolfBoot_get_policy(struct wolfBoot_image* img, uint8_t** policy, uint16_t* policySz);
|
uint8_t* policy, uint32_t* policySz,
|
||||||
int wolfBoot_seal(struct wolfBoot_image* img, int index, const uint8_t* secret, int secret_sz);
|
uint8_t* policyRef, uint32_t policyRefSz);
|
||||||
int wolfBoot_seal_blob(struct wolfBoot_image* img, WOLFTPM2_KEYBLOB* seal_blob, const uint8_t* secret, int secret_sz);
|
int wolfBoot_get_policy(struct wolfBoot_image* img,
|
||||||
int wolfBoot_unseal(struct wolfBoot_image* img, int index, uint8_t* secret, int* secret_sz);
|
uint8_t** policy, uint16_t* policySz);
|
||||||
int wolfBoot_unseal_blob(struct wolfBoot_image* img, WOLFTPM2_KEYBLOB* seal_blob, uint8_t* secret, int* secret_sz);
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int wolfBoot_read_blob(uint32_t nvIndex, WOLFTPM2_KEYBLOB* blob,
|
||||||
|
const uint8_t* auth, uint32_t authSz);
|
||||||
|
int wolfBoot_store_blob(TPMI_RH_NV_AUTH authHandle, uint32_t nvIndex,
|
||||||
|
word32 nvAttributes, WOLFTPM2_KEYBLOB* blob,
|
||||||
|
const uint8_t* auth, uint32_t authSz);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WOLFBOOT_MEASURED_BOOT
|
#ifdef WOLFBOOT_MEASURED_BOOT
|
||||||
|
|
32
options.mk
32
options.mk
|
@ -197,9 +197,14 @@ ifeq ($(SIGN),ED448)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SIGN),RSA2048)
|
ifneq ($(findstring RSA2048,$(SIGN)),)
|
||||||
KEYGEN_OPTIONS+=--rsa2048
|
KEYGEN_OPTIONS+=--rsa2048
|
||||||
SIGN_OPTIONS+=--rsa2048
|
ifeq ($(SIGN),RSA2048ENC)
|
||||||
|
SIGN_OPTIONS+=--rsa2048enc
|
||||||
|
else
|
||||||
|
SIGN_OPTIONS+=--rsa2048
|
||||||
|
endif
|
||||||
|
SIGN_ALG=RSA2048 # helps keystore.c check
|
||||||
WOLFCRYPT_OBJS+= \
|
WOLFCRYPT_OBJS+= \
|
||||||
$(RSA_EXTRA_OBJS) \
|
$(RSA_EXTRA_OBJS) \
|
||||||
$(MATH_OBJS) \
|
$(MATH_OBJS) \
|
||||||
|
@ -232,9 +237,14 @@ ifeq ($(SIGN),RSA2048)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SIGN),RSA3072)
|
ifneq ($(findstring RSA3072,$(SIGN)),)
|
||||||
KEYGEN_OPTIONS+=--rsa3072
|
KEYGEN_OPTIONS+=--rsa3072
|
||||||
SIGN_OPTIONS+=--rsa3072
|
ifeq ($(SIGN),RSA3072ENC)
|
||||||
|
SIGN_OPTIONS+=--rsa3072enc
|
||||||
|
else
|
||||||
|
SIGN_OPTIONS+=--rsa3072
|
||||||
|
endif
|
||||||
|
SIGN_ALG=RSA3072 # helps keystore.c check
|
||||||
WOLFCRYPT_OBJS+= \
|
WOLFCRYPT_OBJS+= \
|
||||||
$(RSA_EXTRA_OBJS) \
|
$(RSA_EXTRA_OBJS) \
|
||||||
$(MATH_OBJS) \
|
$(MATH_OBJS) \
|
||||||
|
@ -270,9 +280,15 @@ ifeq ($(SIGN),RSA3072)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SIGN),RSA4096)
|
ifneq ($(findstring RSA4096,$(SIGN)),)
|
||||||
|
SIGN:=RSA4096
|
||||||
KEYGEN_OPTIONS+=--rsa4096
|
KEYGEN_OPTIONS+=--rsa4096
|
||||||
SIGN_OPTIONS+=--rsa4096
|
ifeq ($(SIGN),RSA4096ENC)
|
||||||
|
SIGN_OPTIONS+=--rsa4096enc
|
||||||
|
else
|
||||||
|
SIGN_OPTIONS+=--rsa4096
|
||||||
|
endif
|
||||||
|
SIGN_ALG=RSA4096 # helps keystore.c check
|
||||||
WOLFCRYPT_OBJS+= \
|
WOLFCRYPT_OBJS+= \
|
||||||
$(RSA_EXTRA_OBJS) \
|
$(RSA_EXTRA_OBJS) \
|
||||||
$(MATH_OBJS) \
|
$(MATH_OBJS) \
|
||||||
|
@ -640,3 +656,7 @@ ifeq ($(FSP), 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS+=$(CFLAGS_EXTRA)
|
CFLAGS+=$(CFLAGS_EXTRA)
|
||||||
|
|
||||||
|
ifeq ($(SIGN_ALG),)
|
||||||
|
SIGN_ALG=$(SIGN)
|
||||||
|
endif
|
||||||
|
|
150
src/image.c
150
src/image.c
|
@ -43,7 +43,47 @@
|
||||||
/* Globals */
|
/* Globals */
|
||||||
static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE];
|
static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||||
|
|
||||||
|
/* TPM based verify */
|
||||||
|
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
||||||
|
static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
|
struct wolfBoot_image *img, uint8_t *sig)
|
||||||
|
{
|
||||||
|
int ret, verify_res = 0;
|
||||||
|
WOLFTPM2_KEY tpmKey;
|
||||||
|
TPM_ALG_ID alg, sigAlg;
|
||||||
|
|
||||||
|
/* Load public key into TPM */
|
||||||
|
memset(&tpmKey, 0, sizeof(tpmKey));
|
||||||
|
|
||||||
|
/* get public key for policy authorization */
|
||||||
|
ret = wolfBoot_load_pubkey(img, &tpmKey, &alg);
|
||||||
|
if (ret == 0) {
|
||||||
|
sigAlg = (alg == TPM_ALG_RSA) ? TPM_ALG_RSASSA : TPM_ALG_ECDSA;
|
||||||
|
ret = wolfTPM2_VerifyHashScheme(&wolftpm_dev, &tpmKey,
|
||||||
|
sig, IMAGE_SIGNATURE_SIZE, /* Signature */
|
||||||
|
img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, /* Hash */
|
||||||
|
sigAlg, WOLFBOOT_TPM_HASH_ALG);
|
||||||
|
}
|
||||||
|
/* unload handle regardless of result */
|
||||||
|
wolfTPM2_UnloadHandle(&wolftpm_dev, &tpmKey.handle);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
verify_res = 1; /* TPM does hash verify compare */
|
||||||
|
|
||||||
|
if ((~(uint32_t)ret == 0xFFFFFFFF) && (verify_res == 1) &&
|
||||||
|
(~(uint32_t)verify_res == 0xFFFFFFFE)) {
|
||||||
|
wolfBoot_image_confirm_signature_ok(img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wolfBoot_printf("TPM verify signature error %d (%s)\n",
|
||||||
|
ret, wolfTPM2_GetRCString(ret));
|
||||||
|
}
|
||||||
|
(void)key_slot;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* wolfCrypt software verify */
|
||||||
#ifdef WOLFBOOT_SIGN_ED25519
|
#ifdef WOLFBOOT_SIGN_ED25519
|
||||||
#include <wolfssl/wolfcrypt/ed25519.h>
|
#include <wolfssl/wolfcrypt/ed25519.h>
|
||||||
static void wolfBoot_verify_signature(uint8_t key_slot,
|
static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
|
@ -123,54 +163,18 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
uint8_t *pubkey = keystore_get_buffer(key_slot);
|
uint8_t *pubkey = keystore_get_buffer(key_slot);
|
||||||
int pubkey_sz = keystore_get_size(key_slot);
|
int pubkey_sz = keystore_get_size(key_slot);
|
||||||
int point_sz = pubkey_sz/2;
|
int point_sz = pubkey_sz/2;
|
||||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
|
||||||
WOLFTPM2_KEY tpmKey;
|
|
||||||
#else
|
|
||||||
ecc_key ecc;
|
ecc_key ecc;
|
||||||
mp_int r, s;
|
mp_int r, s;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (pubkey == NULL || pubkey_sz <= 0) {
|
if (pubkey == NULL || pubkey_sz <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
|
||||||
/* Use TPM for ECC verify */
|
|
||||||
/* Load public key into TPM */
|
|
||||||
memset(&tpmKey, 0, sizeof(tpmKey));
|
|
||||||
ret = wolfTPM2_LoadEccPublicKey(&wolftpm_dev, &tpmKey,
|
|
||||||
TPM2_GetTpmCurve(ECC_KEY_TYPE), /* Curve */
|
|
||||||
pubkey, point_sz, /* Public X */
|
|
||||||
pubkey + point_sz, point_sz /* Public Y */
|
|
||||||
);
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = wolfTPM2_VerifyHashScheme(&wolftpm_dev, &tpmKey,
|
|
||||||
sig, IMAGE_SIGNATURE_SIZE, /* Signature */
|
|
||||||
img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, /* Hash */
|
|
||||||
TPM_ALG_ECDSA, WOLFBOOT_TPM_HASH_ALG);
|
|
||||||
}
|
|
||||||
/* unload handle regardless of result */
|
|
||||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &tpmKey.handle);
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
verify_res = 1; /* TPM does hash verify compare */
|
|
||||||
|
|
||||||
if ((~(uint32_t)ret == 0xFFFFFFFF) && (verify_res == 1) &&
|
|
||||||
(~(uint32_t)verify_res == 0xFFFFFFFE)) {
|
|
||||||
wolfBoot_image_confirm_signature_ok(img);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
wolfBoot_printf("TPM ECC verify error %d (%s)\n",
|
|
||||||
ret, wolfTPM2_GetRCString(ret));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* wolfCrypt software ECC verify */
|
|
||||||
ret = wc_ecc_init(&ecc);
|
ret = wc_ecc_init(&ecc);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* Import public key */
|
/* Import public key */
|
||||||
ret = wc_ecc_import_unsigned(&ecc, pubkey,
|
ret = wc_ecc_import_unsigned(&ecc, pubkey, pubkey + point_sz, NULL,
|
||||||
(byte*)(pubkey + point_sz), NULL, ECC_KEY_TYPE);
|
ECC_KEY_TYPE);
|
||||||
if (ret == 0 && ecc.type == ECC_PUBLICKEY) {
|
if (ret == 0 && ecc.type == ECC_PUBLICKEY) {
|
||||||
/* Import signature into r,s */
|
/* Import signature into r,s */
|
||||||
mp_init(&r);
|
mp_init(&r);
|
||||||
|
@ -182,7 +186,6 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
}
|
}
|
||||||
wc_ecc_free(&ecc);
|
wc_ecc_free(&ecc);
|
||||||
}
|
}
|
||||||
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC521 */
|
#endif /* WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC521 */
|
||||||
|
@ -247,31 +250,6 @@ static int RsaDecodeSignature(uint8_t** pInput, int inputSz)
|
||||||
}
|
}
|
||||||
#endif /* !NO_RSA_SIG_ENCODING */
|
#endif /* !NO_RSA_SIG_ENCODING */
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
int ret = BAD_FUNC_ARG, i;
|
|
||||||
if (output == NULL || pkcsBlockLen < 2 || pkcsBlockLen > 0xFFFF) {
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
/* First byte must be 0x00 and Second byte, block type, 0x01 */
|
|
||||||
if (pkcsBlock[0] != 0 || pkcsBlock[1] != RSA_BLOCK_TYPE_1) {
|
|
||||||
return RSA_PAD_E;
|
|
||||||
}
|
|
||||||
/* check the padding until we find the separator */
|
|
||||||
for (i = 2; i < pkcsBlockLen && pkcsBlock[i++] == 0xFF; ) { }
|
|
||||||
/* Minimum of 11 bytes of pre-message data and must have separator. */
|
|
||||||
if (i < RSA_MIN_PAD_SZ || pkcsBlock[i-1] != 0) {
|
|
||||||
return RSA_PAD_E;
|
|
||||||
}
|
|
||||||
*output = (byte *)(pkcsBlock + i);
|
|
||||||
ret = pkcsBlockLen - i;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY*/
|
|
||||||
|
|
||||||
static void wolfBoot_verify_signature(uint8_t key_slot,
|
static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
struct wolfBoot_image *img, uint8_t *sig)
|
struct wolfBoot_image *img, uint8_t *sig)
|
||||||
{
|
{
|
||||||
|
@ -282,53 +260,12 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
uint8_t *pubkey = keystore_get_buffer(key_slot);
|
uint8_t *pubkey = keystore_get_buffer(key_slot);
|
||||||
int pubkey_sz = keystore_get_size(key_slot);
|
int pubkey_sz = keystore_get_size(key_slot);
|
||||||
word32 inOutIdx = 0;
|
word32 inOutIdx = 0;
|
||||||
#if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)
|
|
||||||
WOLFTPM2_KEY tpmKey;
|
|
||||||
const byte *n = NULL, *e = NULL;
|
|
||||||
word32 nSz = 0, eSz = 0;
|
|
||||||
#else
|
|
||||||
struct RsaKey rsa;
|
struct RsaKey rsa;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (pubkey == NULL || pubkey_sz < 0) {
|
if (pubkey == NULL || pubkey_sz < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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,
|
|
||||||
&n, &nSz, /* modulus */
|
|
||||||
&e, &eSz /* exponent */
|
|
||||||
);
|
|
||||||
if (ret == 0) {
|
|
||||||
/* Load public key into TPM */
|
|
||||||
memset(&tpmKey, 0, sizeof(tpmKey));
|
|
||||||
ret = wolfTPM2_LoadRsaPublicKey_ex(&wolftpm_dev, &tpmKey,
|
|
||||||
n, nSz, *((word32*)e),
|
|
||||||
TPM_ALG_NULL, WOLFBOOT_TPM_HASH_ALG);
|
|
||||||
}
|
|
||||||
if (ret == 0) {
|
|
||||||
/* Perform public decrypt and manually un-pad */
|
|
||||||
ret = wolfTPM2_RsaEncrypt(&wolftpm_dev, &tpmKey,
|
|
||||||
TPM_ALG_NULL, /* no padding */
|
|
||||||
sig, IMAGE_SIGNATURE_SIZE,
|
|
||||||
output, &output_sz);
|
|
||||||
}
|
|
||||||
if (ret == 0) {
|
|
||||||
/* Perform PKCSv1.5 UnPadding */
|
|
||||||
ret = RsaUnPad(output, output_sz, &digest_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
wolfBoot_printf("TPM RSA error %d (%s)\n",
|
|
||||||
ret, wolfTPM2_GetRCString(ret));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &tpmKey.handle);
|
|
||||||
|
|
||||||
#else
|
|
||||||
/* wolfCrypt software RSA verify */
|
/* wolfCrypt software RSA verify */
|
||||||
#if defined(WOLFBOOT_RENESAS_SCEPROTECT) ||\
|
#if defined(WOLFBOOT_RENESAS_SCEPROTECT) ||\
|
||||||
defined(WOLFBOOT_RENESAS_TSIP)
|
defined(WOLFBOOT_RENESAS_TSIP)
|
||||||
|
@ -357,7 +294,6 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
}
|
}
|
||||||
#endif /* SCE || TSIP */
|
#endif /* SCE || TSIP */
|
||||||
wc_FreeRsaKey(&rsa);
|
wc_FreeRsaKey(&rsa);
|
||||||
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY*/
|
|
||||||
|
|
||||||
#ifndef NO_RSA_SIG_ENCODING
|
#ifndef NO_RSA_SIG_ENCODING
|
||||||
if (ret > WOLFBOOT_SHA_DIGEST_SIZE) {
|
if (ret > WOLFBOOT_SHA_DIGEST_SIZE) {
|
||||||
|
@ -438,6 +374,8 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
}
|
}
|
||||||
#endif /* WOLFBOOT_SIGN_LMS */
|
#endif /* WOLFBOOT_SIGN_LMS */
|
||||||
|
|
||||||
|
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the specified header type from the external flash image.
|
* @brief Get the specified header type from the external flash image.
|
||||||
|
|
324
src/tpm.c
324
src/tpm.c
|
@ -308,18 +308,16 @@ int wolfBoot_tpm2_extend(uint8_t pcrIndex, uint8_t* hash, int line)
|
||||||
|
|
||||||
rc = wolfTPM2_ExtendPCR(&wolftpm_dev, pcrIndex, WOLFBOOT_TPM_PCR_ALG, hash,
|
rc = wolfTPM2_ExtendPCR(&wolftpm_dev, pcrIndex, WOLFBOOT_TPM_PCR_ALG, hash,
|
||||||
TPM2_GetHashDigestSize(WOLFBOOT_TPM_PCR_ALG));
|
TPM2_GetHashDigestSize(WOLFBOOT_TPM_PCR_ALG));
|
||||||
#ifdef DEBUG_WOLFTPM
|
#ifdef WOLFBOOT_DEBUG_TPM
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
wolfBoot_printf("Measured boot: Index %d, Line %d\n", pcrIndex, line);
|
wolfBoot_printf("Measured boot: Index %d, Line %d\n", pcrIndex, line);
|
||||||
|
|
||||||
#ifdef WOLFBOOT_DEBUG_TPM
|
|
||||||
rc = wolfTPM2_ReadPCR(&wolftpm_dev, pcrIndex, WOLFBOOT_TPM_PCR_ALG,
|
rc = wolfTPM2_ReadPCR(&wolftpm_dev, pcrIndex, WOLFBOOT_TPM_PCR_ALG,
|
||||||
digest, &digestSz);
|
digest, &digestSz);
|
||||||
|
|
||||||
wolfBoot_printf("PCR %d: Res %d, Digest Sz %d\n",
|
wolfBoot_printf("PCR %d: Res %d, Digest Sz %d\n",
|
||||||
pcrIndex, rc, digestSz);
|
pcrIndex, rc, digestSz);
|
||||||
wolfBoot_print_bin(digest, digestSz);
|
wolfBoot_print_bin(digest, digestSz);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wolfBoot_printf("Measure boot failed! Index %d, %x (%s)\n",
|
wolfBoot_printf("Measure boot failed! Index %d, %x (%s)\n",
|
||||||
|
@ -332,6 +330,83 @@ int wolfBoot_tpm2_extend(uint8_t pcrIndex, uint8_t* hash, int line)
|
||||||
}
|
}
|
||||||
#endif /* WOLFBOOT_MEASURED_BOOT */
|
#endif /* WOLFBOOT_MEASURED_BOOT */
|
||||||
|
|
||||||
|
#if defined(WOLFBOOT_TPM_VERIFY) || defined(WOLFBOOT_TPM_SEAL)
|
||||||
|
int wolfBoot_load_pubkey(struct wolfBoot_image* img, WOLFTPM2_KEY* pubKey,
|
||||||
|
TPM_ALG_ID* pAlg)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
uint32_t key_type;
|
||||||
|
int key_slot = -1;
|
||||||
|
uint8_t *hdr;
|
||||||
|
uint16_t hdrSz;
|
||||||
|
|
||||||
|
*pAlg = TPM_ALG_NULL;
|
||||||
|
|
||||||
|
/* get public key */
|
||||||
|
hdrSz = wolfBoot_get_header(img, HDR_PUBKEY, &hdr);
|
||||||
|
if (hdrSz == WOLFBOOT_SHA_DIGEST_SIZE)
|
||||||
|
key_slot = keyslot_id_by_sha(hdr);
|
||||||
|
if (key_slot < 0)
|
||||||
|
rc = -1;
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
key_type = keystore_get_key_type(key_slot);
|
||||||
|
hdr = keystore_get_buffer(key_slot);
|
||||||
|
hdrSz = keystore_get_size(key_slot);
|
||||||
|
if (hdr == NULL || hdrSz <= 0)
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
/* Parse public key to TPM public key. Note: this loads as temp handle,
|
||||||
|
* however we don't use the handle. We still need to unload it. */
|
||||||
|
if (rc == 0) {
|
||||||
|
#if defined(WOLFBOOT_SIGN_ECC256) || \
|
||||||
|
defined(WOLFBOOT_SIGN_ECC384) || \
|
||||||
|
defined(WOLFBOOT_SIGN_ECC521)
|
||||||
|
int tpmcurve;
|
||||||
|
int point_sz = hdrSz/2;
|
||||||
|
if ( key_type == AUTH_KEY_ECC256) tpmcurve = TPM_ECC_NIST_P256;
|
||||||
|
else if (key_type == AUTH_KEY_ECC384) tpmcurve = TPM_ECC_NIST_P384;
|
||||||
|
else if (key_type == AUTH_KEY_ECC521) tpmcurve = TPM_ECC_NIST_P521;
|
||||||
|
else rc = -1; /* not supported algorithm */
|
||||||
|
if (rc == 0) {
|
||||||
|
*pAlg = TPM_ALG_ECC;
|
||||||
|
rc = wolfTPM2_LoadEccPublicKey(&wolftpm_dev, pubKey,
|
||||||
|
tpmcurve, /* Curve */
|
||||||
|
hdr, point_sz, /* Public X */
|
||||||
|
hdr + point_sz, point_sz /* Public Y */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#elif defined(WOLFBOOT_SIGN_RSA2048) || \
|
||||||
|
defined(WOLFBOOT_SIGN_RSA3072) || \
|
||||||
|
defined(WOLFBOOT_SIGN_RSA4096)
|
||||||
|
uint32_t inOutIdx = 0;
|
||||||
|
const uint8_t*n = NULL, *e = NULL;
|
||||||
|
uint32_t nSz = 0, eSz = 0;
|
||||||
|
if (key_type != AUTH_KEY_RSA2048 && key_type != AUTH_KEY_RSA3072 &&
|
||||||
|
key_type != AUTH_KEY_RSA4096) {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
*pAlg = TPM_ALG_RSA;
|
||||||
|
rc = wc_RsaPublicKeyDecode_ex(hdr, &inOutIdx, hdrSz,
|
||||||
|
&n, &nSz, /* modulus */
|
||||||
|
&e, &eSz /* exponent */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
/* Load public key into TPM */
|
||||||
|
rc = wolfTPM2_LoadRsaPublicKey_ex(&wolftpm_dev, pubKey,
|
||||||
|
n, nSz, *((uint32_t*)e),
|
||||||
|
TPM_ALG_NULL, WOLFBOOT_TPM_HASH_ALG);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
rc = -1; /* not supported */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif /* WOLFBOOT_TPM_VERIFY || WOLFBOOT_TPM_SEAL */
|
||||||
|
|
||||||
#ifdef WOLFBOOT_TPM_SEAL
|
#ifdef WOLFBOOT_TPM_SEAL
|
||||||
int wolfBoot_get_random(uint8_t* buf, int sz)
|
int wolfBoot_get_random(uint8_t* buf, int sz)
|
||||||
{
|
{
|
||||||
|
@ -495,77 +570,136 @@ int wolfBoot_get_policy(struct wolfBoot_image* img,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wolfBoot_load_pubkey(struct wolfBoot_image* img, WOLFTPM2_KEY* pubKey,
|
/* authHandle = TPM_RH_PLATFORM or TPM_RH_OWNER */
|
||||||
TPM_ALG_ID* pAlg)
|
/* auth is optional */
|
||||||
|
int wolfBoot_store_blob(TPMI_RH_NV_AUTH authHandle, uint32_t nvIndex,
|
||||||
|
word32 nvAttributes, WOLFTPM2_KEYBLOB* blob,
|
||||||
|
const uint8_t* auth, uint32_t authSz)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc;
|
||||||
uint32_t key_type;
|
WOLFTPM2_HANDLE parent;
|
||||||
int key_slot = -1;
|
WOLFTPM2_NV nv;
|
||||||
uint8_t *hdr;
|
uint8_t pubAreaBuffer[sizeof(TPM2B_PUBLIC)]; /* oversized buffer */
|
||||||
uint16_t hdrSz;
|
int nvSz, pos, pubAreaSize;
|
||||||
|
|
||||||
*pAlg = TPM_ALG_NULL;
|
memset(&parent, 0, sizeof(parent));
|
||||||
|
memset(&nv, 0, sizeof(nv));
|
||||||
|
|
||||||
/* get public key */
|
nv.handle.hndl = nvIndex;
|
||||||
hdrSz = wolfBoot_get_header(img, HDR_PUBKEY, &hdr);
|
nv.handle.auth.size = authSz;
|
||||||
if (hdrSz == WOLFBOOT_SHA_DIGEST_SIZE)
|
memcpy(nv.handle.auth.buffer, auth, authSz);
|
||||||
key_slot = keyslot_id_by_sha(hdr);
|
|
||||||
if (key_slot < 0)
|
|
||||||
rc = -1;
|
|
||||||
|
|
||||||
|
parent.hndl = authHandle;
|
||||||
|
|
||||||
|
/* encode public for smaller storage */
|
||||||
|
rc = TPM2_AppendPublic(pubAreaBuffer, (word32)sizeof(pubAreaBuffer),
|
||||||
|
&pubAreaSize, &blob->pub);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
key_type = keystore_get_key_type(key_slot);
|
blob->pub.size = pubAreaSize;
|
||||||
hdr = keystore_get_buffer(key_slot);
|
|
||||||
hdrSz = keystore_get_size(key_slot);
|
nvSz = (uint32_t)sizeof(blob->pub.size) + blob->pub.size;
|
||||||
if (hdr == NULL || hdrSz <= 0)
|
nvSz += (uint32_t)sizeof(blob->priv.size) + blob->priv.size;
|
||||||
rc = -1;
|
|
||||||
|
/* Create NV - no auth required, blob encrypted by TPM already */
|
||||||
|
rc = wolfTPM2_NVCreateAuth(&wolftpm_dev, &parent, &nv,
|
||||||
|
nv.handle.hndl, nvAttributes, nvSz, NULL, 0);
|
||||||
|
if (rc == TPM_RC_NV_DEFINED) {
|
||||||
|
/* allow use of existing handle - ignore this error */
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Parse public key to TPM public key. Note: this loads as temp handle,
|
/* write sealed blob to NV */
|
||||||
* however we don't use the handle. We still need to unload it. */
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
#if defined(WOLFBOOT_SIGN_ECC256) || \
|
pos = 0;
|
||||||
defined(WOLFBOOT_SIGN_ECC384) || \
|
/* write pub size */
|
||||||
defined(WOLFBOOT_SIGN_ECC521)
|
rc = wolfTPM2_NVWriteAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
int tpmcurve;
|
(uint8_t*)&blob->pub.size,
|
||||||
int point_sz = hdrSz/2;
|
(uint32_t)sizeof(blob->pub.size), pos);
|
||||||
if ( key_type == AUTH_KEY_ECC256) tpmcurve = TPM_ECC_NIST_P256;
|
}
|
||||||
else if (key_type == AUTH_KEY_ECC384) tpmcurve = TPM_ECC_NIST_P384;
|
if (rc == 0) {
|
||||||
else if (key_type == AUTH_KEY_ECC521) tpmcurve = TPM_ECC_NIST_P521;
|
pos += sizeof(blob->pub.size);
|
||||||
else rc = -1; /* not supported algorithm */
|
/* write pub */
|
||||||
if (rc == 0) {
|
rc = wolfTPM2_NVWriteAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
*pAlg = TPM_ALG_ECC;
|
pubAreaBuffer, blob->pub.size, pos);
|
||||||
rc = wolfTPM2_LoadEccPublicKey(&wolftpm_dev, pubKey,
|
}
|
||||||
tpmcurve, /* Curve */
|
if (rc == 0) {
|
||||||
hdr, point_sz, /* Public X */
|
pos += blob->pub.size;
|
||||||
hdr + point_sz, point_sz /* Public Y */
|
/* write priv size */
|
||||||
);
|
rc = wolfTPM2_NVWriteAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
}
|
(uint8_t*)&blob->priv.size,
|
||||||
#elif defined(WOLFBOOT_SIGN_RSA2048) || \
|
(uint32_t)sizeof(blob->priv.size), pos);
|
||||||
defined(WOLFBOOT_SIGN_RSA3072) || \
|
}
|
||||||
defined(WOLFBOOT_SIGN_RSA4096)
|
if (rc == 0) {
|
||||||
uint32_t inOutIdx = 0;
|
pos += sizeof(blob->priv.size);
|
||||||
const uint8_t*n = NULL, *e = NULL;
|
/* write priv */
|
||||||
uint32_t nSz = 0, eSz = 0;
|
rc = wolfTPM2_NVWriteAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
if (key_type != AUTH_KEY_RSA2048 && key_type != AUTH_KEY_RSA3072 &&
|
blob->priv.buffer, blob->priv.size, pos);
|
||||||
key_type != AUTH_KEY_RSA4096) {
|
}
|
||||||
rc = -1;
|
if (rc == 0) {
|
||||||
}
|
pos += blob->priv.size;
|
||||||
if (rc == 0) {
|
}
|
||||||
*pAlg = TPM_ALG_RSA;
|
if (rc == 0) {
|
||||||
rc = wc_RsaPublicKeyDecode_ex(hdr, &inOutIdx, hdrSz,
|
wolfBoot_printf("Wrote %d bytes to NV index 0x%x\n",
|
||||||
&n, &nSz, /* modulus */
|
pos, nv.handle.hndl);
|
||||||
&e, &eSz /* exponent */
|
}
|
||||||
);
|
else {
|
||||||
}
|
wolfBoot_printf("Error %d writing blob to NV index %x (error %s)\n",
|
||||||
if (rc == 0) {
|
rc, nv.handle.hndl, wolfTPM2_GetRCString(rc));
|
||||||
/* Load public key into TPM */
|
}
|
||||||
rc = wolfTPM2_LoadRsaPublicKey_ex(&wolftpm_dev, pubKey,
|
return rc;
|
||||||
n, nSz, *((uint32_t*)e),
|
}
|
||||||
TPM_ALG_NULL, WOLFBOOT_TPM_HASH_ALG);
|
|
||||||
}
|
int wolfBoot_read_blob(uint32_t nvIndex, WOLFTPM2_KEYBLOB* blob,
|
||||||
#else
|
const uint8_t* auth, uint32_t authSz)
|
||||||
rc = -1; /* not supported */
|
{
|
||||||
#endif
|
int rc;
|
||||||
|
WOLFTPM2_NV nv;
|
||||||
|
uint8_t pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
|
||||||
|
uint32_t readSz;
|
||||||
|
int nvSz, pubAreaSize = 0, pos;
|
||||||
|
|
||||||
|
memset(&nv, 0, sizeof(nv));
|
||||||
|
|
||||||
|
nv.handle.hndl = nvIndex;
|
||||||
|
nv.handle.auth.size = authSz;
|
||||||
|
memcpy(nv.handle.auth.buffer, auth, authSz);
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
readSz = sizeof(blob->pub.size);
|
||||||
|
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
|
(uint8_t*)&blob->pub.size, &readSz, pos);
|
||||||
|
if (rc == 0) {
|
||||||
|
pos += readSz;
|
||||||
|
readSz = blob->pub.size;
|
||||||
|
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
|
pubAreaBuffer, &readSz, pos);
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
pos += readSz;
|
||||||
|
rc = TPM2_ParsePublic(&blob->pub, pubAreaBuffer,
|
||||||
|
(word32)sizeof(pubAreaBuffer), &pubAreaSize);
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
readSz = sizeof(blob->priv.size);
|
||||||
|
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
|
(uint8_t*)&blob->priv.size, &readSz, pos);
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
pos += sizeof(blob->priv.size);
|
||||||
|
readSz = blob->priv.size;
|
||||||
|
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
|
blob->priv.buffer, &readSz, pos);
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
pos += blob->priv.size;
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
wolfBoot_printf("Read %d bytes from NV index 0x%x\n",
|
||||||
|
pos, nv.handle.hndl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wolfBoot_printf("Error %d reading blob from NV index %x (error %s)\n",
|
||||||
|
rc, nv.handle.hndl, wolfTPM2_GetRCString(rc));
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -642,6 +776,7 @@ int wolfBoot_seal_blob(struct wolfBoot_image* img, WOLFTPM2_KEYBLOB* seal_blob,
|
||||||
}
|
}
|
||||||
|
|
||||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &policy_session.handle);
|
wolfTPM2_UnloadHandle(&wolftpm_dev, &policy_session.handle);
|
||||||
|
wolfTPM2_UnsetAuth(&wolftpm_dev, 1);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -653,22 +788,31 @@ int wolfBoot_seal(struct wolfBoot_image* img, int index,
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
WOLFTPM2_KEYBLOB seal_blob;
|
WOLFTPM2_KEYBLOB seal_blob;
|
||||||
|
word32 nvAttributes;
|
||||||
|
|
||||||
memset(&seal_blob, 0, sizeof(seal_blob));
|
memset(&seal_blob, 0, sizeof(seal_blob));
|
||||||
|
|
||||||
|
/* creates a sealed keyed hash object (not loaded to TPM) */
|
||||||
rc = wolfBoot_seal_blob(img, &seal_blob, secret, secret_sz);
|
rc = wolfBoot_seal_blob(img, &seal_blob, secret, secret_sz);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
#ifdef WOLFBOOT_DEBUG_TPM
|
#ifdef WOLFBOOT_DEBUG_TPM
|
||||||
wolfBoot_printf("Sealed keyed hash (pub %d, priv %d bytes):\n",
|
wolfBoot_printf("Sealed keyed hash (pub %d, priv %d bytes):\n",
|
||||||
seal_blob.pub.size, seal_blob.priv.size);
|
seal_blob.pub.size, seal_blob.priv.size);
|
||||||
//wolfBoot_print_bin((uint8_t*)&seal_blob.pub, (uint32_t)sizeof(seal_blob.pub));
|
|
||||||
//wolfBoot_print_bin(seal_blob.priv.buffer, seal_blob.priv.size);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* TODO: store sealed blob in TPM NV */
|
/* Get NV attributes amd allow it to be locked (if desired) */
|
||||||
(void)index;
|
wolfTPM2_GetNvAttributesTemplate(TPM_RH_PLATFORM, &nvAttributes);
|
||||||
//wolfTPM2_GetNvAttributesTemplate
|
nvAttributes |= TPMA_NV_WRITEDEFINE;
|
||||||
//wolfTPM2_NVCreateAuth
|
|
||||||
//wolfTPM2_NVWriteAuth
|
rc = wolfBoot_store_blob(TPM_RH_PLATFORM,
|
||||||
|
WOLFBOOT_TPM_SEAL_NV_BASE + index,
|
||||||
|
nvAttributes, &seal_blob,
|
||||||
|
NULL, 0 /* auth is not required as sealed blob is already encrypted */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (rc != 0) {
|
||||||
|
wolfBoot_printf("Error %d sealing secret! (%s)\n",
|
||||||
|
rc, wolfTPM2_GetRCString(rc));
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -817,30 +961,35 @@ int wolfBoot_unseal_blob(struct wolfBoot_image* img, WOLFTPM2_KEYBLOB* seal_blob
|
||||||
|
|
||||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &seal_blob->handle);
|
wolfTPM2_UnloadHandle(&wolftpm_dev, &seal_blob->handle);
|
||||||
wolfTPM2_UnloadHandle(&wolftpm_dev, &policy_session.handle);
|
wolfTPM2_UnloadHandle(&wolftpm_dev, &policy_session.handle);
|
||||||
|
wolfTPM2_UnsetAuth(&wolftpm_dev, 1);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wolfBoot_unseal(struct wolfBoot_image* img, int index, uint8_t* secret, int* secret_sz)
|
int wolfBoot_unseal(struct wolfBoot_image* img, int index, uint8_t* secret,
|
||||||
|
int* secret_sz)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
WOLFTPM2_KEYBLOB seal_blob;
|
WOLFTPM2_KEYBLOB seal_blob;
|
||||||
|
|
||||||
memset(&seal_blob, 0, sizeof(seal_blob));
|
memset(&seal_blob, 0, sizeof(seal_blob));
|
||||||
|
|
||||||
/* TODO: get sealed blob in TPM NV */
|
rc = wolfBoot_read_blob(WOLFBOOT_TPM_SEAL_NV_BASE + index, &seal_blob,
|
||||||
(void)index;
|
NULL, 0 /* auth is not required as sealed blob is already encrypted */
|
||||||
//wolfTPM2_NVReadPublic
|
);
|
||||||
//wolfTPM2_NVReadAuth
|
|
||||||
|
|
||||||
rc = wolfBoot_unseal_blob(img, &seal_blob, secret, secret_sz);
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
|
rc = wolfBoot_unseal_blob(img, &seal_blob, secret, secret_sz);
|
||||||
#ifdef WOLFBOOT_DEBUG_TPM
|
#ifdef WOLFBOOT_DEBUG_TPM
|
||||||
wolfBoot_printf("Unsealed keyed hash (pub %d, priv %d bytes):\n",
|
if (rc == 0) {
|
||||||
seal_blob.pub.size, seal_blob.priv.size);
|
wolfBoot_printf("Unsealed keyed hash (pub %d, priv %d bytes):\n",
|
||||||
//wolfBoot_print_bin((uint8_t*)&seal_blob.pub, (uint32_t)sizeof(seal_blob.pub));
|
seal_blob.pub.size, seal_blob.priv.size);
|
||||||
//wolfBoot_print_bin(seal_blob.priv.buffer, seal_blob.priv.size);
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (rc != 0) {
|
||||||
|
wolfBoot_printf("Error %d unsealing secret! (%s)\n",
|
||||||
|
rc, wolfTPM2_GetRCString(rc));
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#endif /* WOLFBOOT_TPM_SEAL */
|
#endif /* WOLFBOOT_TPM_SEAL */
|
||||||
|
@ -1009,8 +1158,7 @@ int wolfBoot_check_rot(int key_slot, uint8_t* pubkey_hint)
|
||||||
rc = wolfTPM2_SetAuthSession(&wolftpm_dev, 1, &wolftpm_session,
|
rc = wolfTPM2_SetAuthSession(&wolftpm_dev, 1, &wolftpm_session,
|
||||||
(TPMA_SESSION_decrypt | TPMA_SESSION_encrypt |
|
(TPMA_SESSION_decrypt | TPMA_SESSION_encrypt |
|
||||||
TPMA_SESSION_continueSession));
|
TPMA_SESSION_continueSession));
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
{
|
|
||||||
/* find index with matching digest */
|
/* find index with matching digest */
|
||||||
nv.handle.hndl = WOLFBOOT_TPM_KEYSTORE_NV_BASE + key_slot;
|
nv.handle.hndl = WOLFBOOT_TPM_KEYSTORE_NV_BASE + key_slot;
|
||||||
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
|
||||||
|
@ -1020,11 +1168,11 @@ int wolfBoot_check_rot(int key_slot, uint8_t* pubkey_hint)
|
||||||
wolfBoot_printf("TPM Root of Trust valid (id %d)\n", key_slot);
|
wolfBoot_printf("TPM Root of Trust valid (id %d)\n", key_slot);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (rc >= 0) rc = -1; /* failure */
|
||||||
wolfBoot_printf("TPM Root of Trust failed! %d (%s)\n",
|
wolfBoot_printf("TPM Root of Trust failed! %d (%s)\n",
|
||||||
rc, wolfTPM2_GetRCString(rc));
|
rc, wolfTPM2_GetRCString(rc));
|
||||||
wolfBoot_printf("Expected Hash %d\n", digestSz);
|
wolfBoot_printf("Expected Hash %d\n", digestSz);
|
||||||
wolfBoot_print_hexstr(pubkey_hint, digestSz, 0);
|
wolfBoot_print_hexstr(pubkey_hint, digestSz, 0);
|
||||||
if (rc >= 0) rc = -1; /* failure */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wolfTPM2_UnsetAuth(&wolftpm_dev, 1);
|
wolfTPM2_UnsetAuth(&wolftpm_dev, 1);
|
||||||
|
|
|
@ -575,13 +575,12 @@ int wolfBoot_unlock_disk(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct wolfBoot_image img;
|
struct wolfBoot_image img;
|
||||||
WOLFTPM2_KEYBLOB seal_blob;
|
|
||||||
uint8_t secret[WOLFBOOT_MAX_SEAL_SZ];
|
uint8_t secret[WOLFBOOT_MAX_SEAL_SZ];
|
||||||
int secretSz;
|
int secretSz;
|
||||||
uint8_t* policy = NULL;
|
uint8_t* policy = NULL;
|
||||||
uint16_t policySz = 0;
|
uint16_t policySz = 0;
|
||||||
|
int nvIndex = 0; /* where the sealed blob is stored in NV */
|
||||||
|
|
||||||
memset(&seal_blob, 0, sizeof(seal_blob));
|
|
||||||
memset(secret, 0, sizeof(secret));
|
memset(secret, 0, sizeof(secret));
|
||||||
|
|
||||||
wolfBoot_printf("Unlocking disk...\n");
|
wolfBoot_printf("Unlocking disk...\n");
|
||||||
|
@ -597,38 +596,49 @@ int wolfBoot_unlock_disk(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* for testing seal and unseal */
|
/* try to unseal the secret */
|
||||||
/* create secret to seal */
|
ret = wolfBoot_unseal(&img, nvIndex, secret, &secretSz);
|
||||||
secretSz = 32;
|
if (ret != 0) { /* if secret does not exist, expect TPM_RC_HANDLE here */
|
||||||
ret = wolfBoot_get_random(secret, secretSz);
|
if ((ret & RC_MAX_FMT1) == TPM_RC_HANDLE) {
|
||||||
if (ret == 0) {
|
wolfBoot_printf("Sealed secret does not exist!\n");
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* create secret to seal */
|
||||||
|
secretSz = 32;
|
||||||
|
ret = wolfBoot_get_random(secret, secretSz);
|
||||||
|
if (ret == 0) {
|
||||||
|
wolfBoot_printf("Creating new secret (%d bytes)\n", secretSz);
|
||||||
|
wolfBoot_print_hexstr(secret, secretSz, 0);
|
||||||
|
|
||||||
wolfBoot_printf("Unsealed %d bytes\n", secretCheckSz);
|
/* seal new secret */
|
||||||
wolfBoot_print_hexstr(secretCheck, secretCheckSz, 0);
|
ret = wolfBoot_seal(&img, nvIndex, secret, secretSz);
|
||||||
TPM2_ForceZero(secretCheck, sizeof(secretCheck));
|
}
|
||||||
|
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(&img, nvIndex, secretCheck, &secretCheckSz);
|
||||||
|
if (ret == 0) {
|
||||||
|
if (secretSz != secretCheckSz ||
|
||||||
|
memcmp(secret, secretCheck, secretSz) != 0)
|
||||||
|
{
|
||||||
|
wolfBoot_printf("secret check mismatch!\n");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wolfBoot_printf("Secret Check %d bytes\n", secretCheckSz);
|
||||||
|
wolfBoot_print_hexstr(secretCheck, secretCheckSz, 0);
|
||||||
|
TPM2_ForceZero(secretCheck, sizeof(secretCheck));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
wolfBoot_printf("Secret %d bytes\n", secretSz);
|
||||||
|
wolfBoot_print_hexstr(secret, secretSz, 0);
|
||||||
|
|
||||||
/* TODO: Unlock disk */
|
/* TODO: Unlock disk */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue